次のコマンドは、現在のディレクトリ内のすべてのファイルを列挙し*.txt
、それらを1つずつ処理しようとします。
for line in "find . -iname '*.txt'"; do
echo $line
ls -l $line;
done
次のエラーが発生するのはなぜですか?:
ls: invalid option -- 'e'
Try `ls --help' for more information.
ファイル名のスペースと改行を処理するため、ファイルをループするより良い方法を次に示します。
#!/bin/bash
find . -type f -iname "*.txt" -print0 | while IFS= read -r -d $'\0' line; do
echo "$line"
ls -l "$line"
done
for
-loop は、指定された文字列の (スペースで区切られた) 各エントリを反復処理します。
find
コマンドを実際に実行するのではなく、文字列として指定します (-loop によって反復されfor
ます)。二重引用符の代わりに、バッククォートまたは$()
:
for line in $(find . -iname '*.txt'); do
echo "$line"
ls -l "$line"
done
さらに、ファイルのパス/名前にスペースが含まれている場合、このメソッドは失敗します (for
ループはスペースで区切られたエントリを反復するため)。代わりに、dogbanes answerで説明されている方法を使用することをお勧めします。
エラーを明確にするには:
前述のように、for line in "find . -iname '*.txt'";
スペースで区切られたすべてのエントリを反復処理します。
最初の 2 つは (望ましくない動作を除いて) エラーにはなりませんが、3 番目は実行時に問題があります。
ls -l -iname
多くの (bash) コマンドは 1 文字のオプションを組み合わせることができるため-iname
、 と同じ-i -n -a -m -e
です。そして出来上がり:あなたのinvalid option -- 'e'
エラー!
ファイル名にスペースと改行を使用した、よりコンパクトなバージョン:
find . -iname '*.txt' -exec sh -c 'echo "{}" ; ls -l "{}"' \;
コマンドを文字列として渡す代わりに、引用符の代わりにコマンド置換を使用して find を実行します。
for line in $(find . -iname '*.txt'); do
echo $line
ls -l $line;
done