シェルスクリプト 初級

Bashのループ処理(for/while/until)

for・while・untilループの書き方と使い分けを学び、ファイル処理やカウンタ制御などの実践的なパターンを身につける

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

ループをマスターすることで、繰り返し作業の自動化や大量ファイルの一括処理が一気に楽になります。まずは小さなスクリプトで試しながら使い方に慣れていきましょう。