この質問は
に触発されていますシェルループを使用して、悪い習慣と見なされるテキストを処理するのはなぜですか?
これらの構成が表示されます
`find内のファイルのfor file in `find . -type f -name ...`; do smth with ${file}; done
および
for dir in $(find . -type d -name ...); do smth with ${dir}; done
なぜこの種の投稿を避けるべきなのかを説明するために時間をかけて投稿にコメントする人がいたとしても、ここではほぼ毎日使用されています…
そのような投稿の数を見る(そして時々それらのコメントが単純であるという事実無視)私は質問したほうがいいと思いました:
find
をループしているのはなぜですか の出力の悪い習慣と、find
によって返されるファイル名/パスごとに1つ以上のコマンドを実行する適切な方法は何ですか。 ?
承認された回答:
問題
for f in $(find .)
互換性のない2つのものを組み合わせます。
find
改行文字で区切られたファイルパスのリストを出力します。その$(find .)
を離れるときに呼び出されるsplit+glob演算子 そのリストコンテキストで引用符で囲まれていない場合は、$IFS
の文字で分割されます (デフォルトでは改行が含まれますが、スペースとタブ(およびzsh
のNULも含まれます) ))そして、結果の各単語に対してグロビングを実行します(zsh
を除く) )(さらに、ksh93またはpdksh派生物のブレース拡張も!)
あなたがそれを成し遂げたとしても:
IFS='
' # split on newline only
set -o noglob # disable glob (also disables brace expansion in pdksh
# but not ksh93)
for f in $(find .) # invoke split+glob
改行文字はファイルパス内の文字と同じように有効であるため、これはまだ間違っています。 find -print
の出力 単純に後処理を確実に行うことはできません(ここに示すように複雑なトリックを使用する場合を除きます)。 。
これは、シェルがfind
の出力を保存する必要があることも意味します 完全に実行してから、ファイルのループを開始する前に、分割してグロブします(これは、その出力を2回目にメモリに保存することを意味します)。
find . | xargs cmd
同様の問題があります(空白、改行、一重引用符、二重引用符、円記号があります(xarg
もあります)。 有効な文字の一部を形成しない実装バイト)は問題です)
より正しい代替案
for
を使用する唯一の方法 find
の出力をループします zsh
を使用することになります IFS =$'をサポートします