Loops are fundamental building blocks of shell scripts. Bash provides for loops (over lists and ranges), while loops (condition-based), and until loops (run until condition is true). Mastering these patterns lets you automate repetitive tasks, process files in bulk, and build robust automation scripts.
ShellBashLoopsScriptingfor fruit in apple banana cherry; do echo "Processing: $fruit" done
fruit) in turn. The loop body runs once for each item between do and done.for ((i=1; i<=5; i++)); do echo "Step $i of 5" done
for file in *.txt; do echo "Processing $file" wc -l "$file" done
"$file" to handle filenames with spaces correctly. If no files match, the glob is passed literally — add shopt -s nullglob to avoid this.for user in $(cat users.txt); do echo "Creating account for $user" done
$() to loop over the output of a command. This splits on whitespace by default. For lines with spaces, use while read instead (see below) which handles spaces in values correctly.count=1 while [ $count -le 5 ]; do echo "Count: $count" ((count++)) done
[ ] test uses -le (less than or equal). Use (( )) for arithmetic operations on the counter.while IFS= read -r line; do echo "Line: $line" done < filename.txt
IFS= prevents leading/trailing whitespace from being stripped. -r prevents backslash interpretation. The < redirects the file to the while loop's stdin.until curl -sf http://localhost:8080/health; do echo "Waiting for service..." sleep 2 done echo "Service is up!"
for i in 1 2 3 4 5; do
if [ $i -eq 3 ]; then
break
fi
echo "$i"
done
# Output: 1 2
break immediately exits the innermost loop. In nested loops, break 2 exits two levels up. Use break when you've found what you're looking for and don't need to continue iterating.for i in 1 2 3 4 5; do
if [ $i -eq 3 ]; then
continue
fi
echo "$i"
done
# Output: 1 2 4 5
continue skips the rest of the current iteration and moves to the next one. Use it to skip invalid items, error conditions, or items that don't match your criteria without breaking the entire loop.servers=("web1" "web2" "db1" "cache1")
for server in "${servers[@]}"; do
echo "Deploying to: $server"
done
"${array[@]}" to expand all array elements as separate quoted words. The double quotes and @ together ensure elements with spaces are handled correctly. This is the standard pattern for iterating over bash arrays.for item in list; do ... done for iterating over known items or files.while condition; do ... done when the number of iterations is not known upfront.while IFS= read -r line; do ... done < file for safe line-by-line file processing.for loops iterate over a finite list (array, files, command output). while loops repeat as long as a condition is true, making them suitable for indefinite loops like polling or reading streams. Use for when you know the items to iterate; use while for condition-based repetition.
A for loop with command substitution splits on all whitespace (spaces, tabs, newlines) and can break lines with spaces into multiple iterations. while IFS= read -r line reads exactly one line at a time, preserving spaces within lines and handling all edge cases correctly.
Append & inside the loop to run each iteration as a background job, then use wait after the loop: for f in *.log; do process "$f" & done; wait. For more control over parallelism, use xargs -P N or the GNU parallel command.