Bash цикл for: перебор чисел, файлов и элементов массива

Категория: Bash · Язык: Bash · Обновлено:

Цикл for в Bash перебирает значения: for i in 1 2 3; do echo "$i"; done. Диапазон задаётся записью {1..10}, файлы перебираются маской *.txt, а элементы массива перебираются через "${arr[@]}".

Перебор списка значений

Bash
for fruit in яблоко груша слива; do
  echo "Фрукт: $fruit"
done

Та же запись в одну строку:

Bash
for fruit in яблоко груша слива; do echo "Фрукт: $fruit"; done

Диапазон чисел

Bash
for i in {1..5}; do echo "$i"; done        # 1 2 3 4 5
for i in {0..20..5}; do echo "$i"; done    # с шагом 5: 0 5 10 15 20
for i in $(seq 1 3); do echo "$i"; done    # через seq, работает и с переменными

Запись {1..N} не принимает переменные: {1..$n} не сработает. В таком случае используйте seq 1 "$n" или цикл в стиле C.

Цикл в стиле C

Bash
n=4
for ((i = 1; i <= n; i++)); do
  echo "шаг $i"
done

Перебор файлов

Bash
for file in /tmp/demo/*.txt; do
  echo "Файл: $file ($(wc -l < "$file") строк)"
done

Кавычки вокруг $file обязательны: без них имена с пробелами разобьются на части. Если подходящих файлов нет, Bash оставит в переменной сам шаблон. Проверьте это:

Bash
for file in /tmp/demo/*.csv; do
  [ -e "$file" ] || continue     # пропустить, если ничего не найдено
  echo "$file"
done

Элементы массива

Bash
servers=("web-1" "web-2" "db 1")

for server in "${servers[@]}"; do
  echo "Проверяю: $server"
done

echo "Всего: ${#servers[@]}"

Запись "${servers[@]}" в кавычках сохраняет элементы с пробелами, как db 1.

Прервать или пропустить шаг

Bash
for i in {1..10}; do
  (( i % 2 == 0 )) && continue    # пропустить чётные
  (( i > 7 )) && break            # остановиться после 7
  echo "$i"
done

Строки файла: не for, а while

Для чтения файла построчно for не подходит, потому что делит текст по пробелам. Используйте while read:

Bash
while IFS= read -r line; do
  echo "Строка: $line"
done < /tmp/demo/a.txt

Частые вопросы

Почему for i in {1..$n} не работает?

Расширение фигурных скобок выполняется до подстановки переменных. Используйте seq или for ((i=1; i<=n; i++)).

Как использовать результат команды в цикле?

for pid in $(pgrep nginx); do ... подходит для коротких списков без пробелов в значениях. Для остальных случаев используйте while read и mapfile.