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
検索する拡張バージョンを渡します。さまざまな状況がある可能性があります。
*.txt
現在、ディレクトリに一致するファイルはありません。 findはリテラルを使用します*.txt
(デフォルトのbash設定を想定しています)。*.txt
現在のディレクトリにあるファイルが1つだけ一致しているとします。a.txt
findはこのファイル名を使用し、a.txt
現在のディレクトリから始まるfindという名前のすべてのファイルと一致します。現在のディレクトリに一致するファイルが複数あります
*.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
コマンドに渡します。これを引用符で囲むと、シェルにリテラル文字列をに渡すように指示できます*.txt
。find
別のエスケープ方法(またはfind . -name \*.txt
)を使用して同じ保護を得ることができますfind . -name '*.txt'
。