跳轉到

建立 2026-09-14 更新 2026-09-14

迴圈

迴圈用來處理「一堆檔」或「一直等到條件成立」。Bash 最常用的是 forwhile

for 走清單

for f in *.txt; do
  echo "處理 $f"
  wc -l -- "$f"
done

in 後面由 shell 展開。沒有匹配到任何 *.txt 時,有些設定會把字面上的 *.txt 當成檔名。較穩的寫法:

shopt -s nullglob
for f in *.txt; do
  ...
done

參數逐個處理:

for arg in "$@"; do
  echo "收到:$arg"
done

一定要用 "$@",不要用無引號的 $@$*,否則有空白的檔名會裂開。

數列:

for i in $(seq 1 5); do
  echo "$i"
done

# Bash 也支援
for ((i = 1; i <= 5; i++)); do
  echo "$i"
done

while 讀檔或等到成功

while IFS= read -r line; do
  echo "行:$line"
done < /etc/hosts
  • IFS= 避免把行首行尾空白切掉
  • -r 避免反斜線被當成跳脫
  • < 檔 把檔案接到迴圈的 stdin

讀指令輸出:

df -h | while IFS= read -r line; do
  echo "$line"
done

注意:管線右邊的 while 在子 shell 裡跑,裡面改的變數迴圈結束後會消失。要累加計數,改用 here-string 或程序替換:

while IFS= read -r line; do
  count=$((count + 1))
done < <(find . -name '*.log')

跳過與提前結束

for f in *; do
  [[ -f $f ]] || continue
  grep -q secret "$f" && break
done
  • continue:下一輪
  • break:離開迴圈

不要用 for 讀檔的每一行

# 不推薦:空白與萬用字元會搞砸
for line in $(cat file.txt); do
  ...
done

讀行請用 while readfor 適合「已經是分開的項目」:檔名、參數、數字。

總結

清單用 for ... in "$@"*.ext;讀行用 while read。迴圈裡的指令失敗時,搭配 條件判斷set -e 決定要停還是繼續。重複出現的片段可以抽成 函式