Bash Loops — for, while, until, break, continue, and Safe Iteration

A programming workstation with a source-code editor and terminal output on a computer display, illustrating repetitive Bash shell automation.

A loop is a Bash control structure that repeats commands. It can visit a list of filenames, count a series of attempts, or keep checking a condition until a result changes. Linux administrators use loops to review many files and automate repeatable checks without typing the same command for every item. The governing reference is the GNU Bash manual’s looping-constructs section.

Elementary Overview

Imagine inspecting every shelf in a room. You could write one instruction for each shelf, or write a single instruction that means “inspect the next shelf until there are no shelves left.” A shell loop works the same way. A for loop usually walks through a group of items; a while loop continues while a test succeeds; and an until loop continues until a test succeeds. They all need a sensible reason to stop.

Objectives and Prerequisites

By the end of this reference, you should be able to select the correct loop, predict its stopping condition, use break and continue, process paths containing spaces, and read a text file one line at a time. Review shell and script fundamentals, Bash variables and quoting, and conditional tests and exit statuses first. The examples use Bash rather than a generic POSIX sh shell.

The for Loop: Repeating a Command for Each Item

A list-style for loop assigns each item to a variable, then runs its body once for that item. The item list is determined before the body begins. Quoting "$zone" protects the value if it contains spaces or wildcard characters. The surrounding do and done keywords mark the repeated commands.

for zone in east west central; do
  printf 'Inspecting %s\n' "$zone"
done

The example prints three lines, one per region. Bash also provides an arithmetic form suitable for counters: for (( i=1; i<=3; i++ )). The counter form is convenient for a known number of repetitions; list iteration is usually clearer for filenames, hosts, or user-supplied arguments. When passing script arguments through a loop, use for item in "$@", not for item in $*, to keep each argument intact.

Learn Linux TV demonstrates Bash for-loop syntax and repeating commands for multiple items, including a practical automation example.

Safe File Iteration and Paths With Spaces

A glob such as *.log can identify matching files, but a pattern that matches nothing ordinarily stays literal in Bash. The following guard skips that case and avoids acting on non-regular files. Because the directory and filename variable are quoted, a name such as night shift.log stays one filename. Review command lookup and filesystem paths when adapting it to another directory.

log_dir="$HOME/logs"
for file in "$log_dir"/*.log; do
  [[ -f "$file" ]] || continue
  printf 'Log file: %s\n' "${file##*/}"
done

This script only lists matching names; it does not delete, rename, or rewrite files. Before applying a loop to production systems, confirm its target directory and permissions. File ownership and access-control lists may affect what can be read even when a path is visible.

The while Loop: Repeat While a Test Succeeds

A while loop evaluates its condition before each iteration. In the common [[ ... ]] form, exit status zero means the test succeeded. When the condition stops succeeding, Bash leaves the loop. The body must change the relevant state if termination depends on that state; otherwise a loop can run indefinitely.

attempt=1
while (( attempt <= 3 )); do
  printf 'Attempt %d\n' "$attempt"
  attempt=$((attempt + 1))
done

The output is Attempt 1, Attempt 2, then Attempt 3. Incrementing the counter with assignment works predictably even when a script enables set -e. A standalone ((counter++)) can return a nonzero status when its evaluated old value is zero, which may unexpectedly stop such scripts.

Learn Linux TV walks through Bash while-loop conditions, repetition and practical refinements in a Linux terminal.

The until Loop: Repeat Until Success

An until loop reverses the condition logic of while. It repeats while its test is unsuccessful and stops once the test succeeds. That is useful for bounded retry logic, provided retries have a fixed limit or a timeout. The example below demonstrates the condition without touching a network or production service.

ready=0
until (( ready == 3 )); do
  printf 'Waiting: %d\n' "$ready"
  ready=$((ready + 1))
done
printf 'Ready: %d\n' "$ready"

The counter reaches three, the until condition succeeds, and the loop stops. A real service-readiness check should also handle persistent failure, use appropriate delays, and distinguish a healthy response from merely receiving any output. This is especially useful when inspecting Linux service startup behavior during maintenance.

Shawn Powers compares for, while and until loops in Bash and explains when each repetition structure is appropriate.

Break, Continue, and Loop Control

The break builtin leaves the nearest enclosing loop immediately. The continue builtin skips the rest of the current pass and returns to the next iteration or condition check. In nested loops, Bash can also accept a numeric level, but that should be used with care because it changes which loop receives control.

for number in 1 2 3 4 5; do
  if (( number == 2 )); then
    continue
  fi
  if (( number == 5 )); then
    break
  fi
  printf '%d\n' "$number"
done

This prints 1, 3, and 4. It skips two and stops before printing five. Avoid hiding complex failure handling behind many nested break statements; a clear function with a return status is often easier to test and maintain.

Reading Files Line by Line

For text input, prefer while IFS= read -r line over for word in $(cat file). The latter splits content on whitespace and can change literal text. Setting IFS= preserves leading and trailing spaces; -r prevents backslash interpretation. The extra condition below preserves a final nonempty line even when the source file lacks a trailing newline.

input_file="$HOME/hosts.txt"
while IFS= read -r line || [[ -n $line ]]; do
  printf 'Entry: %s\n' "$line"
done < "$input_file"

Redirecting the file into the loop keeps the loop in the current shell, so counters set inside its body remain available afterward. By contrast, sending data through a pipeline into while read may run the loop body in a subshell; whether variables survive depends on execution context and Bash options. Always test scripts against empty files, filenames with spaces, and missing inputs.

Troubleshooting and Common Failures

If a loop never stops, inspect the test and verify that the body changes its controlling variable. If a filename breaks into separate words, look for missing quotation marks or command substitution used to construct a list. If a glob is processed literally, check whether the directory exists and whether any files match. If a loop exits prematurely under set -e, examine arithmetic command statuses and other failures rather than assuming the final command printed an error.

To inspect syntax without running commands, use bash -n script.sh. For trace output, use bash -x script.sh in a safe environment; traces may reveal secrets embedded in variables or arguments. For additional static warnings, consult ShellCheck. None of these checks establishes that a script is safe for production; review the actions and scope separately.

Practical Exercises and Knowledge Check

Create a disposable directory containing two .log files, one with a space in its name, and adapt the file loop to print their basenames. Next, modify the attempt counter so the while loop runs exactly five times. Then change the until example to stop when a counter reaches two. Finally, use break to exit when an item equals stop and continue to ignore skip.

Check your understanding: Which loop most directly walks through existing arguments? Which one continues while the test returns zero? What does until do when the test first succeeds? Why is "$@" important for filenames or phrases containing spaces? The answers are: list-style for; while; it stops; and it preserves the boundaries of individual arguments.

Further Reading

The authoritative syntax and exit-status rules are in the GNU Bash Reference Manual: Looping Constructs. For a broader treatment of word splitting and quoting, see Shell Expansions and Bourne Shell Builtins. These references describe actual language behavior rather than a particular instructor’s preferred style.

Elementary Conclusion

A Bash loop is a reusable instruction for doing the same kind of work more than once. Use for when you already have items to visit, while when work should continue while something is true, and until when work should continue until something becomes true. The most important habit is to know what makes the loop stop and to protect the names and values it handles.

Editor’s Note: We volunteer daily to ensure the credibility of the information on this platform is Verifiably True. If you would like to support our work and help further secure the integrity of our research initiatives, please scan the QR code below to donate 5,000 sats.

BitcoinVersus.Tech original Bitcoin donation QR code for a 5,000 satoshi donation

For mobile scanning, open this lesson on a larger screen and use a compatible Bitcoin wallet to scan the original QR code. Verify the address before sending 5,000 sats: 3C9o19EH5HSiwEPyCTmEKzxhNCbo2X6TTb.

BitcoinVersus.tech is not a financial advisor. This media platform reports on financial subjects purely for informational purposes.

Leave a Reply