Циклы for и while

Повторяем действия для списка элементов или пока выполняется условие.

Цикл — это конструкция, которая повторяет блок команд: for перебирает список, while работает, пока истинно условие.

for по списку

Самый частый вид: пройти по списку слов, файлов или элементов массива.

for env in dev staging prod; do
  echo "Деплою в $env"
done

Вывод:

Деплою в dev
Деплою в staging
Деплою в prod

Очень полезно перебирать файлы по шаблону — Bash сам подставит подходящие имена:

for f in *.log; do
  echo "Архивирую $f"
  gzip "$f"
done

Числовой for в C-стиле

for ((i = 1; i <= 3; i++)); do
  echo "Попытка $i"
done

Вывод:

Попытка 1
Попытка 2
Попытка 3

Эта форма с двойными скобками удобна, когда нужен счётчик с шагом.

while: пока условие истинно

while повторяет блок, пока команда-условие возвращает 0. Классика — построчное чтение файла:

while read -r line; do
  echo "Строка: $line"
done < users.txt

Здесь read читает по строке из файла, поданного через < users.txt, и возвращает неуспех в конце файла — тогда цикл останавливается. Опция -r отключает обработку обратных слэшей и нужна почти всегда.

Управление циклом: break и continue

for n in 1 2 3 4 5; do
  if [ "$n" -eq 3 ]; then
    continue
  fi
  if [ "$n" -eq 5 ]; then
    break
  fi
  echo "$n"
done

Вывод:

1
2
4

continue пропускает текущую итерацию (3 не напечаталось), break выходит из цикла совсем (на 5 остановились).

Как работает под капотом

В for x in список Bash сначала полностью раскрывает список (подставляет переменные и шаблоны), получает набор слов и проходит по ним по одному. Поэтому for f in *.log работает: шаблон превращается в список реальных файлов ещё до начала цикла. А while read читает поток лениво, строку за строкой, не загружая весь файл в память, — поэтому он годится для огромных файлов.

Частые ошибки

  • for line in $(cat file). Так файл разобьётся по словам, а не по строкам. Для построчного чтения нужен while read -r line.
  • Шаблон не совпал. Если *.log ничего не нашёл, без опции nullglob цикл выполнится один раз с буквальным *.log. Проверяйте существование файла внутри.
  • Забыли -r у read. Тогда обратные слэши в строках исказятся.

Итог

  • for x in список; do ... done перебирает слова, файлы по шаблону или элементы массива.
  • Числовой for ((i=0; i<n; i++)) удобен для счётчиков.
  • while read -r line; do ... done < file — правильный способ читать файл построчно; break/continue управляют циклом.
Проверьте себя
1. Какой способ правильно читать файл построчно?
Afor line in $(cat file)
Bwhile read -r line; do ... done < file
Cfor ((i=0; i<file; i++))
Dcat file | for line
2. Что делает continue внутри цикла?
AВыходит из цикла полностью
BПропускает оставшуюся часть текущей итерации и переходит к следующей
CЗавершает скрипт
DПовторяет ту же итерацию заново
3. Почему for f in *.log работает с реальными файлами?
Aread знает про файлы
BBash раскрывает шаблон *.log в список существующих имён до начала цикла
CЭто особый синтаксис цикла
Dgzip подставляет файлы