Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

while / until

『while』はコマンドの終了ステータスが真(0)の間ループを繰り返します。『until』はその逆で、偽になる間繰り返します。ファイルを1行ずつ読み込む処理でも頻繁に使います。

構文
# while ループ
while 条件; do
    処理
done

# until ループ(条件が偽の間繰り返す)
until 条件; do
    処理
done

# ファイルを1行ずつ読み込む
while IFS= read -r line; do
    処理
done < ファイル名

# パイプ経由で読み込む(サブシェル注意)
コマンド | while IFS= read -r line; do
    処理
done

# 無限ループ
while true; do
    処理
done
構文パターン一覧
パターン概要
while [ 条件 ]条件が真の間ループを繰り返します。
while (( 条件 ))算術条件が非ゼロの間繰り返します。
until [ 条件 ]条件が偽の間ループを繰り返します。
while truebreak で明示的に抜けるまで無限に繰り返します。
while IFS= read -r lineファイルを1行ずつ安全に読み込みます。
breakループを途中で終了します。
continue現在のイテレーションをスキップします。
サンプルコード

基本的な『while』ループでカウンタを1から5まで処理します。

#!/bin/bash
count=1
while [ $count -le 5 ]; do
    echo "カウント: $count"
    (( count++ ))
done
カウント: 1
カウント: 2
カウント: 3
カウント: 4
カウント: 5

『until』は条件が偽の間ループします。『while』の逆の動作です。

n=0
until [ $n -ge 5 ]; do
    echo "n = $n"
    (( n++ ))
done
n = 0
n = 1
n = 2
n = 3
n = 4

ファイルを1行ずつ読み込む定番パターンです。『IFS=』でスペースを保持し、『-r』でバックスラッシュをそのまま扱います。

while IFS= read -r line; do
    echo "行: $line"
done < /etc/hosts
行: 127.0.0.1	localhost
行: 255.255.255.255	broadcasthost
行: ::1             localhost

無限ループはプロセス監視などに使います。『break』で明示的に抜けます。

while true; do
    if ! pgrep -x "myapp" > /dev/null; then
        echo "myapp が停止しています。再起動します"
        ./myapp &
    fi
    sleep 60
done

『IFS』を変更してCSVファイルのフィールドを分割します。

while IFS=',' read -r name score grade; do
    echo "名前: $name, スコア: $score, 評価: $grade"
done <<'EOF'
Alice,95,A
Bob,78,C
Charlie,88,B
EOF
名前: Alice, スコア: 95, 評価: A
名前: Bob, スコア: 78, 評価: C
名前: Charlie, スコア: 88, 評価: B

パイプ経由でコマンドの出力を1行ずつ処理します。

find . -name "*.php" | while IFS= read -r file; do
    lines=$(wc -l < "$file")
    echo "$file: $lines 行"
done
./index.php: 120 行
./ajax.php: 85 行
概要

ファイルを行単位で処理するときは while IFS= read -r line; do ... done < ファイル が定番パターンです。IFS= を指定しないと行頭・行末の空白が削除され、-r を付けないとバックスラッシュが展開されてしまいます。

パイプ経由の while は別サブシェルで実行されます。そのため while ループ内で変数を更新しても、ループ終了後に外側のシェルから参照できません。変数を引き継ぐには入力リダイレクト(< <(コマンド))や一時ファイルを使います。

リストの繰り返しには for の方が適しています。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。