まくまくLinux/Shellノート
シェルスクリプト: 外部コマンドの実行結果を一行ずつ処理する
2017-11-01

パイプで while read につなぐ方法

例えば、find . -name '*.sh' といった外部コマンド(カレントディレクトリ以下の .sh ファイルを再帰的に列挙する)の出力結果を一行ずつ処理するには、下記のようにパイプで while read に繋ぎます。

find . -name '*.sh' | while read line; do
  echo "$line"
done

line という部分は変数名なので別の名前に変えても大丈夫です。 この例では1ファイルずつループ処理しているので、file という変数名の方が直観的かもしれません。

$line をダブルクォートで囲んでいるのは、echo が連続したスペースを 1 つのスペースにまとめて出力してしまうのを防ぐためです。 パス内にスペースが含まれていなければ問題は発生しませんが、必ずダブルクォートで囲むようにしましょう。

外部コマンドの出力を配列として受け取る方法

パイプを使用せず、$(command) の形で実行した外部コマンドの出力を、配列で受け取る方法もあります。

list=$(find . -name '*.sh')
for line in "$list"; do
  echo "$line"
done

外部コマンドの出力を1行ずつ正しくループ処理するために、$list をダブルクォートで囲むことを忘れないでください。 for ループの in の後ろには、スペース区切りで各要素が列挙されているものとして認識されます。 行内にスペースが含まれている場合に、行全体を1つの要素として処理するためには、$list 変数を展開するときにダブルクォートで囲んでおく必要があります。

2017-11-01