web-dev-qa-db-ja.com

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

while loopを使用して、bashでコマンドの出力を読み取ろうとしています。

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が発生しました。

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

必要な出力:

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

間違いがあります。< <(command)ではなく<<<$(command)が必要です

< <( )プロセス置換 であり、$()コマンド置換 および<<<here-stringです。

59
Gilles Quenot

ファイル名に改行文字を含めることを妨げるものは何もないことに注意してください。各ファイルに対してコマンドを実行する正規の方法found findを使用します。

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

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

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

また、スクリプトで「read」コマンドを呼び出す正規の方法(入力で追加の処理を実行したくない場合)は次のとおりです。

IFS= read -r var

-rは、readがバックスラッシュ文字を特別に(セパレーターと改行のエスケープ文字として)処理するのを停止し、IFS =は、セパレーターのリストをreadの空の文字列に設定します(それ以外の場合そのリストに空白文字があった場合、それらは入力の最初と最後から削除されます)。

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

14

パイプを使用したい場合は、コマンドを置き換える必要はありません。

find . -type f |
while read -r line
do
    echo "$line"
done

すでに述べたように、findの場合は-execオプション。