Bash Loops: for, while, until, and Flow Control

Loops are where Bash scripts shift from one-off commands to repeatable processing. The key is choosing the right loop for the data and stop condition you have.

Table of Contents

This post focuses on practical loop patterns that are safe and readable.

for Loops

while and until Loops

Loop Control Statements

Series Navigation

for loops

Iterate fixed value sets

A for loop is ideal when iterating known values.

for env_name in dev stage prod; do
  echo "processing environment: $env_name"
done

You can also iterate file globs:

for file in ./*.log; do
  echo "log file: $file"
done

Use C style arithmetic loops

This style is useful for index-based logic.

for ((i=1; i<=5; i++)); do
  echo "attempt $i"
done

while and until loops

Read files line by line

Use while IFS= read -r line to preserve whitespace and backslashes.

while IFS= read -r line; do
  echo "line: $line"
done < server-list.txt

Avoid piping into while read when you need loop side effects outside the loop scope.

Retry with until

until loops run until a command succeeds.

attempt=0

until curl -fsS https://thelinux.pro >/dev/null; do
  attempt=$((attempt + 1))
  echo "health check failed on attempt $attempt"
  sleep 2
done

echo "service is reachable"

Loop control statements

Break out early

break exits the current loop as soon as a condition is met.

for host in web1 web2 web3; do
  if ping -c 1 "$host" >/dev/null 2>&1; then
    echo "first reachable host: $host"
    break
  fi
done

Skip one iteration with continue

continue skips only the current item and keeps looping.

while IFS= read -r filename; do
  [[ -z "$filename" ]] && continue
  [[ "$filename" == \#* ]] && continue
  echo "processing: $filename"
done < deploy-files.txt

Practical script example

#!/usr/bin/env bash

success_count=0

for target in "$@"; do
  if [[ ! -f "$target" ]]; then
    echo "missing file: $target"
    continue
  fi

  echo "valid file: $target"
  success_count=$((success_count + 1))
done

echo "processed $success_count valid files"

Next in this series

Next, we will finish the series with functions, set -euo pipefail, trap, and script structure patterns that make Bash code maintainable in production.