Bash:コマンドの出力を一度に1行ずつ読み込む方法は?

Bash:コマンドの出力を一度に1行ずつ読み込む方法は?

.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

バグがあります。< <(command)必要ありません。<<<$(command)

< <( )プロセスの交換$()はいコマンドの置き換えそして<<<ここにある文字列

答え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バックスラッシュ文字(区切り文字と改行のエスケープ文字)の特別な処理を停止し、readIFS =は区切り文字のリストを空の文字列に設定しますread(そうでない場合は、空白文字がリストにある場合は入力の開始から削除されます)。そして終わり)。

シェルでループを使用するのは一般的に悪い考えです(何百ものクラス2ツールに対して1つ以上のツールを順番に実行するのではなく、複数のツールを使用して同時に操作できるシェルでタスクを実行する方法ではありません。 )。

答え4

小さな修正Stefan Chazerasの答え

find . -type f -exec bash -c 'echo $0; head $0;' {} \;

これは、提供されたスクリプトがbash -c最初のパラメータを使用する方法を示しています。

関連情報