TL; DR:最も正確な回答を得るためにここにいるのであれば、おそらく私の個人的な好みが必要ですfind . -name '*.txt' -exec process {} \;
(この投稿の下部を参照してください)。時間がある場合は、残りを読んで、いくつかの異なる方法とそれらのほとんどの問題を確認してください。
完全な答え:
最善の方法は、何をしたいかによって異なりますが、いくつかのオプションがあります。サブツリー内のファイルやフォルダーの名前に空白が含まれていない限り、ファイルをループするだけです。
for i in $x; do # Not recommended, will break on whitespace
process "$i"
done
やや良い、一時変数を切り取りますx
:
for i in $(find -name \*.txt); do # Not recommended, will break on whitespace
process "$i"
done
可能な場合は、グロブする方がはるかに優れています。現在のディレクトリ内のファイルの場合、空白スペースセーフ:
for i in *.txt; do # Whitespace-safe but not recursive.
process "$i"
done
このglobstar
オプションを有効にすると、このディレクトリとすべてのサブディレクトリで一致するすべてのファイルをグロブできます。
# Make sure globstar is enabled
shopt -s globstar
for i in **/*.txt; do # Whitespace-safe and recursive
process "$i"
done
場合によっては、たとえばファイル名がすでにファイル内にある場合は、次を使用する必要がありますread
。
# IFS= makes sure it doesn't trim leading and trailing whitespace
# -r prevents interpretation of \ escapes.
while IFS= read -r line; do # Whitespace-safe EXCEPT newlines
process "$line"
done < filename
read
find
区切り文字を適切に設定することにより、と組み合わせて安全に使用できます。
find . -name '*.txt' -print0 |
while IFS= read -r -d '' line; do
process "$line"
done
より複雑な検索の場合はfind
、-exec
オプションを使用するか、-print0 | xargs -0
:を使用することをお勧めします。
# execute `process` once for each file
find . -name \*.txt -exec process {} \;
# execute `process` once with all the files as arguments*:
find . -name \*.txt -exec process {} +
# using xargs*
find . -name \*.txt -print0 | xargs -0 process
# using xargs with arguments after each filename (implies one run per filename)
find . -name \*.txt -print0 | xargs -0 -I{} process {} argument
find
こともできます使用してコマンドを実行する前に、各ファイルのディレクトリにcd -execdir
の代わりに-exec
、インタラクティブ行うことができます(各ファイルに対してコマンドを実行する前にプロンプト)を使用して、-ok
代わりに-exec
(または-okdir
代わりに-execdir
)。
*:技術的には、find
とxargs
(デフォルトでは)の両方が、すべてのファイルを通過するのに必要な回数だけ、コマンドラインに収まるだけの引数を指定してコマンドを実行します。実際には、非常に多数のファイルがない限り問題にならず、長さを超えてもすべて同じコマンドラインで必要な場合は、SOLは別の方法を見つけます。