Bashのループ処理(for/while/until)
繰り返し処理はシェルスクリプトの要です。Bashには for・while・until の3種類のループ構文があります。
それぞれの書き方と使いどころを、具体的な例を通じて学びましょう。
1. for ループ
1-1. リストをひとつずつ処理する
最もよく使う形です。スペース区切りのリストを順番に処理します。
for 変数 in リスト; do
# 処理
done
#!/bin/bash
for fruit in apple banana cherry; do
echo "好きな果物: $fruit"
done
好きな果物: apple
好きな果物: banana
好きな果物: cherry
1-2. 数値の範囲をループする(brace expansion)
{開始..終了} を使うと数値の連番を簡単に生成できます。
#!/bin/bash
for i in {1..5}; do
echo "カウント: $i"
done
カウント: 1
カウント: 2
カウント: 3
カウント: 4
カウント: 5
ステップ数を指定するには {開始..終了..ステップ} と書きます。
for i in {0..10..2}; do
echo "$i"
done
# → 0 2 4 6 8 10
1-3. C言語スタイルの for ループ
カウンタを細かく制御したい場合は (( ... )) 構文を使います。
for (( 初期化; 条件; 更新 )); do
# 処理
done
#!/bin/bash
for (( i=1; i<=5; i++ )); do
echo "i = $i"
done
i = 1
i = 2
i = 3
i = 4
i = 5
逆順にしたい場合:
for (( i=5; i>=1; i-- )); do
echo "カウントダウン: $i"
done
1-4. ファイルをループ処理する
ワイルドカードを使えばディレクトリ内のファイルを一括処理できます。
#!/bin/bash
for file in /etc/*.conf; do
echo "設定ファイル: $file"
done
設定ファイル: /etc/adduser.conf
設定ファイル: /etc/debconf.conf
設定ファイル: /etc/deluser.conf
...
注意: ファイル名にスペースが含まれる可能性がある場合、変数は必ず
"$file"のようにダブルクォートで囲んでください。
2. while ループ
2-1. 基本構文
条件が 真(0) の間、処理を繰り返します。
while [ 条件式 ]; do
# 処理
done
#!/bin/bash
count=1
while [ "$count" -le 5 ]; do
echo "count = $count"
count=$(( count + 1 ))
done
count = 1
count = 2
count = 3
count = 4
count = 5
2-2. ファイルを1行ずつ読み込む
while read はテキストファイルや標準入力を1行ずつ処理するときの定番パターンです。
#!/bin/bash
while IFS= read -r line; do
echo "行: $line"
done < /etc/hostname
IFS=: 行頭・行末の空白を維持する-r: バックスラッシュをエスケープとして解釈しない
コマンドの出力を1行ずつ処理する場合はパイプを使います。
ls /tmp | while IFS= read -r file; do
echo "ファイル: $file"
done
2-3. 無限ループと break
条件に true を指定すると無限ループになります。break で抜けます。
#!/bin/bash
count=0
while true; do
count=$(( count + 1 ))
echo "試行回数: $count"
if [ "$count" -ge 3 ]; then
echo "3回到達。ループ終了。"
break
fi
done
試行回数: 1
試行回数: 2
試行回数: 3
3回到達。ループ終了。
2-4. continue で次のイテレーションへスキップ
continue を使うと、現在のイテレーションの残りをスキップして次へ進みます。
#!/bin/bash
for i in {1..6}; do
if [ $(( i % 2 )) -eq 0 ]; then
continue # 偶数はスキップ
fi
echo "奇数: $i"
done
奇数: 1
奇数: 3
奇数: 5
3. until ループ
条件が 偽(0以外) の間、処理を繰り返します。while の逆の動作です。
until [ 条件式 ]; do
# 処理
done
#!/bin/bash
count=1
until [ "$count" -gt 5 ]; do
echo "count = $count"
count=$(( count + 1 ))
done
count = 1
count = 2
count = 3
count = 4
count = 5
until は「〜になるまで待つ」という意味合いで使われることが多いです。
#!/bin/bash
# ファイルが作成されるまで待つ例
until [ -f /tmp/ready.flag ]; do
echo "待機中..."
sleep 1
done
echo "ファイルが見つかりました。処理を開始します。"
4. ループの使い分けまとめ
| ループ | 使いどころ |
|---|---|
for ... in | リストや配列・ファイル一覧を順番に処理したい |
for (( )) | カウンタを細かく制御したい |
while | 「条件を満たす間」繰り返したい(ファイル読み込みにも最適) |
until | 「条件を満たすまで」繰り返したい(待機処理に便利) |
練習問題
問題1
1から100までの整数のうち、3の倍数のみを表示するスクリプトを書いてください。
問題2
/etc/ 以下の .conf ファイルを全て調べ、ファイル名(フルパス)と行数を表示するスクリプトを書いてください。(ヒント: wc -l で行数を取得できます)
問題3
ユーザーに数値を入力させ、その数値が偶数か奇数かを表示するスクリプトを書いてください。ユーザーが 0 を入力したらループを終了してください。(ヒント: read コマンドで標準入力を受け取れます)
解答例
問題1の解答
#!/bin/bash
for i in {1..100}; do
if [ $(( i % 3 )) -eq 0 ]; then
echo "$i"
fi
done
3
6
9
...
99
問題2の解答
#!/bin/bash
for file in /etc/*.conf; do
if [ -f "$file" ]; then
lines=$(wc -l < "$file")
echo "$file : ${lines}行"
fi
done
/etc/adduser.conf : 147行
/etc/debconf.conf : 62行
/etc/deluser.conf : 33行
...
問題3の解答
#!/bin/bash
while true; do
echo -n "数値を入力してください(0で終了): "
read num
if [ "$num" -eq 0 ]; then
echo "終了します。"
break
fi
if [ $(( num % 2 )) -eq 0 ]; then
echo "$num は偶数です"
else
echo "$num は奇数です"
fi
done
数値を入力してください(0で終了): 7
7 は奇数です
数値を入力してください(0で終了): 4
4 は偶数です
数値を入力してください(0で終了): 0
終了します。
まとめ
| 構文 | 例 |
|---|---|
| リストを処理 | for f in *.txt; do ... done |
| 連番 | for i in {1..10}; do ... done |
| Cスタイル | for (( i=0; i<10; i++ )); do ... done |
| 条件ループ | while [ "$x" -lt 10 ]; do ... done |
| 行読み込み | while IFS= read -r line; do ... done < file |
| 条件まで待つ | until [ -f flag ]; do sleep 1; done |
| ループを抜ける | break |
| 次へスキップ | continue |
ループをマスターすることで、繰り返し作業の自動化や大量ファイルの一括処理が一気に楽になります。まずは小さなスクリプトで試しながら使い方に慣れていきましょう。