.bashrcファイルを使用してbashからコマンド出力を読み取ろうとしますwhile loop
。
while read -r line
do
echo "$line"
done <<< $(find . -type f)
私が得た結果
ranveer@ranveer:~/tmp$ bash test.sh
./test.py ./test1.py ./out1 ./test.sh ./out ./out2 ./hello
ranveer@ranveer:~/tmp$
その後私は試しました
$(find . -type f) |
while read -r line
do
echo "$line"
done
しかし、エラーが発生しましたtest.sh: line 5: ./test.py: Permission denied
。
それでは、現在の行全体を一度に読むと思うので、1行ずつどのように読みますか?
希望の出力:
./test.py
./test1.py
./out1
./test.sh
./out
./out2
./hello
答え1
答え2
パイプを使用する場合は、コマンドの置き換えは不要です。基本的read
に読み込みなstdin
ので、入力をパイプできます。
find . -type f -print0 |
while read -r -d '' line
do
echo "$line"
done
または一行で
find . -type f -print0 | while read -r -d '' line; do echo "$line"; done
-print0
とを使用すると、-d ''
ファイル名に新しい行が発生する可能性があるため、デフォルトでは行末が次のようになりますread
(およびを使用して変更できます-d
)。''
上記で使用されたのは実際にはヌルバイトbash
(と同じ$'\0'
)です。
find
すでに述べたもう一つの方法は 's オプションを使うことです-exec
。これはパフォーマンスの面で最良のオプションである可能性が高いです(-exec cmd {} +
処理されているすべての行に対してプロセスを分岐しないようにバリアントを使用することを忘れないでください)。ただし、実際にはwhile
ループ内で実行する操作と処理中のデータの量によって異なります。お客様の場合、差異は無視することも許可される場合もあります。
答え3
ファイル名に改行文字が含まれるのを防ぐことはできません。各ファイルに対してコマンドを実行する正式な方法確立されたはいを検索して
find . -type f -exec cmd {} \;
Bashでタスクを実行するには:
find . -type f -exec bash -c '
for file do
something with "$file"
done' bash {} +
また、スクリプトで「読み取り」コマンドを呼び出す正式な方法は次のとおりです(入力の追加処理を望まない場合)。
IFS= read -r var
-r
バックスラッシュ文字(区切り文字と改行のエスケープ文字)の特別な処理を停止し、read
IFS =は区切り文字のリストを空の文字列に設定しますread
(そうでない場合は、空白文字がリストにある場合は入力の開始から削除されます)。そして終わり)。
シェルでループを使用するのは一般的に悪い考えです(何百ものクラス2ツールに対して1つ以上のツールを順番に実行するのではなく、複数のツールを使用して同時に操作できるシェルでタスクを実行する方法ではありません。 )。
答え4
小さな修正Stefan Chazerasの答え。
find . -type f -exec bash -c 'echo $0; head $0;' {} \;
これは、提供されたスクリプトがbash -c
最初のパラメータを使用する方法を示しています。