「find」で引用パラメータは何をしますか? [コピー]

「find」で引用パラメータは何をしますか? [コピー]

txt ファイルが見つかったら、次のコマンドを実行します。

find . -name "*.txt" -print

これにより、現在のディレクトリにあるすべてのテキストファイルのリストが表示されます。

ただし、find . -name *.txt -print次のエラーが発生しました。 find: paths must precede expression: mein.txt

これは通常予想される動作ですか?引用の違いは何ですか?

答え1

引用符のないトークンでは、実行中のコマンドではなくシェルで拡張が実行されます。

つまりfind . -name "*.txt" -print、ユーザーが入力すると、findはリテラルを*.txt引数の1つとして受け取り、このパターンをオプションの引数として使用します。-nameこれはアプリケーションの前に見つけたファイル名と一致します-print

一方、 と入力すると、find . -name *.txt -printシェルは*.txt検索する拡張バージョンを渡します。さまざまな状況がある可能性があります。

  1. *.txt現在、ディレクトリに一致するファイルはありません。 findはリテラルを使用します*.txt(デフォルトのbash設定を想定しています)。

  2. *.txt現在のディレクトリにあるファイルが1つだけ一致しているとします。a.txtfindはこのファイル名を使用し、a.txt現在のディレクトリから始まるfindという名前のすべてのファイルと一致します。

  3. 現在のディレクトリに一致するファイルが複数あります*.txt(あなたの場合のようです)。-name最初のファイルを引数として受け取り、他のファイルは検索する追加のパス引数であり、式の前にすべてのパスを提供しないと文句を言います。

これは予想される動作です。


以下のファイル階層を想定しています。

.
├── a.txt
├── b.txt
├── c.txt
└── foo
    ├── a.txt
    ├── b.txt
    └── c.txt

各場合に find が受け取った実際の引数は、find 呼び出しを に置き換えて観察できますprintf '%s\n'。この呼び出しは、各拡張引数を独自の行に出力します。

$ printf '%s\n' . -name "*.txt" -print
.
-name
*.txt
-print

$ printf '%s\n' . -name *.txt -print
.
-name
a.txt
b.txt
c.txt
-print

ご覧のとおり、既存のファイルを考慮すると、投稿した2番目の呼び出しはfind . -name a.txt b.txt c.txt -print

答え2

これは予想される動作です。これを「シェルグロビング」といいます。引用符がない場合、*.txtシェルは拡張され、式に一致するファイルの完全なリストをfindコマンドに渡します。これを引用符で囲むと、シェルにリテラル文字列をに渡すように指示できます*.txtfind別のエスケープ方法(またはfind . -name \*.txt)を使用して同じ保護を得ることができますfind . -name '*.txt'

関連情報