Bash:コマンドの出力から一度に1行を読み取る方法は?


49

を使用して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

だから、私は現在それが一度に行全体を丸lurみしていると思うので、どのように行ごとに読むのですか?

必要な出力:

./test.py
./test1.py
./out1
./test.sh
./out
./out2
./hello

3
Bash FAQ 01-避けるべきトラップに関する有用な情報とアドバイスをたくさん読むことをお勧めします。
jw013

while readパートについては、IFSの理解とそこにリンクされている質問を参照してください。
ジル「SO-悪であるのをやめる」

回答:


54

間違いがあります、あなたは必要< <(command)ありません<<<$(command)

< <( )あるプロセスの置換$()あるコマンド置換<<<され、ここで、文字列


2
@RanRag $( )すべてを回避しようとするのはやめてください!これがコマンド置換の構文です。これは、コマンド出力を使用する唯一の方法です。パイプとプロセス置換、およびhere-stringは他のものであり、当然、すべて異なる構文を持っています。何をしているのかを本当に知っているのでなければ、ファイル名を解析するべきではありません。
jw013

働いてくれてありがとうProcess Substitution
RanRag

@ jw013:私はbash初心者です。将来的にはあなたの提案が私の心に残ります。
RanRag

13

ファイル名に改行文字が含まれることを妨げるものは何もないことに注意してください。findで見つかった各ファイルに対してコマンドを実行する標準的な方法は次のとおりです。

find . -type f -exec cmd {} \;

そして、あなたが物事をbashでやりたい場合:

find . -type f -exec bash -c '
  for file do
    something with "$file"
  done' bash {} +

また、スクリプトで「読み取り」コマンドを呼び出す標準的な方法は(入力で余分な処理を行わない場合)です。

IFS= read -r var

-rreadバックスラッシュ文字を特別に処理するのをやめること(区切り文字と改行のエスケープ文字として)、およびIFS =は、区切り文字のリストを空の文字列に設定しますread(そうしないと、空白文字がそのリストにある場合、入力の開始と終了)。

シェルでループを使用することは通常悪い考えです(1つ以上のツールを何百回も連続して実行するのではなく、複数のツールをまとめてタスクとして同時に実行するシェルでの処理方法ではありません)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.