Linux シェルスクリプト: 外部コマンドの実行結果を 1 行ずつ処理する (for, while, read)

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

外部コマンドの出力結果を 1 行ずつ変数に取得しながらループ処理するには、コマンドの出力をパイプ (|) で while read につなぎます。 次の例では、外部コマンド find . -name '*.sh'(カレントディレクトリ以下の .sh ファイルを再帰的に列挙)の出力結果を 1 行ずつ line 変数に取得してループ処理しています。

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

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

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

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

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

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

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