Sagar.BlogArticle
All posts
All posts
Bash

while and until Loops — Condition-Based Iteration

Loop as long as a condition is true (while) or until it becomes true (until). Learn polling loops, reading files line-by-line, and infinite loops with controlled exits.

January 14, 20266 min read
BashLoopswhileControl Flow

The while loop runs a block of commands as long as a condition (command) exits successfully. Its inverse, until, runs until a condition succeeds. These are the go-to loops when you don't know in advance how many iterations you need.

while Loop Basics

# Basic while loop
count=1
while [[ $count -le 5 ]]; do
    echo "Count: $count"
    (( count++ ))
done

# while with arithmetic condition (cleaner for numbers)
i=10
while (( i > 0 )); do
    echo "$i"
    (( i-- ))
done

# while true — infinite loop (exit with break)
while true; do
    echo "Press Ctrl+C to stop"
    sleep 1
done

Reading a File Line by Line

The most important use of while in Bash is processing a file one line at a time:

# Read /etc/hosts line by line
while IFS= read -r line; do
    echo "Line: $line"
done < /etc/hosts

# Read from command output
while IFS= read -r line; do
    echo "Processing: $line"
done < <(grep "ERROR" /var/log/syslog)

# Explanation of the idioms:
# IFS=                 — don't strip leading/trailing whitespace
# read -r              — don't interpret backslashes as escapes
# < file               — redirect file to the while loop's stdin
# < <(command)         — redirect command output (process substitution)

IFS= and read -r are not optional

Without IFS=, read strips leading and trailing whitespace from each line — breaking indented or whitespace-significant content.

Without -r, backslashes are treated as escape characters — a line ending in \ gets joined with the next line.

Always use while IFS= read -r line as the canonical form.

until Loop

# until runs until condition is TRUE (opposite of while)
count=1
until [[ $count -gt 5 ]]; do
    echo "Count: $count"
    (( count++ ))
done

# Polling — wait until file appears
until [[ -f /tmp/ready.flag ]]; do
    echo "Waiting for ready.flag..."
    sleep 2
done
echo "Ready!"

Polling and Retry Loops

#!/usr/bin/env bash
# Wait for a service to respond, with timeout

max_attempts=10
attempt=0
host="localhost"
port=8080

while true; do
    (( attempt++ ))
    if nc -z "$host" "$port" 2>/dev/null; then
        echo "Service is up after $attempt attempts"
        break
    fi

    if (( attempt >= max_attempts )); then
        echo "Service did not start after $max_attempts attempts" >&2
        exit 1
    fi

    echo "Attempt $attempt/$max_attempts — waiting..."
    sleep 3
done

while with Multiple Conditions

# AND condition
a=1 b=10
while [[ $a -lt 5 && $b -gt 3 ]]; do
    echo "a=$a, b=$b"
    (( a++ ))
    (( b -= 2 ))
done

# Read multiple fields per line (IFS splits into variables)
while IFS=: read -r user pass uid gid gecos home shell; do
    echo "User: $user, Shell: $shell"
done < /etc/passwd
Quick Check

When is `until condition` the right choice over `while condition`?

Exercise

Write a script retry.sh that:

  1. Takes a command as argument(s) (e.g., ./retry.sh curl https://example.com)
  2. Runs the command up to 5 times
  3. If it succeeds (exit code 0), print "Success on attempt N" and stop
  4. If all 5 attempts fail, print "Failed after 5 attempts" and exit 1
  5. Wait 2 seconds between attempts