This article explains how to use the Bash while loop, a control structure that repeats a block of commands as long as a given condition is true. You will learn the syntax, see practical examples for reading files, iterating over numbers, and building menus, and understand common pitfalls like infinite loops and off-by-one errors.
What is a Bash while loop?
A while loop in Bash is a programming construct that executes a list of commands repeatedly as long as a given condition evaluates to true. The condition is tested before each iteration, so if it is false at the start, the loop body never runs. This makes while ideal for situations where you don’t know in advance how many times you need to iterate, such as reading lines from a file until the end, waiting for a process to finish, or monitoring a system resource.
Basic syntax and structure
The general syntax is:
while [ condition ]
do
# commands to run
# update the condition or counter
done
You can also write it on a single line with semicolons:
while [ condition ]; do commands; done
Key points:
- The condition is usually a test command inside square brackets
[ ... ]or double brackets[[ ... ]](Bash-specific). - The
doanddonekeywords mark the start and end of the loop body. - If the condition is true, the body runs; then the condition is checked again. This repeats until the condition becomes false.
- You can use
breakto exit the loop early andcontinueto skip the rest of the current iteration and jump to the next one.
Practical examples
1. Counting loop with a counter
The most common use is a counter that increments each iteration:
#!/bin/bash
counter=1
while [ $counter -le 5 ]
do
echo "Iteration $counter"
((counter++))
done
This prints Iteration 1 through Iteration 5. The condition $counter -le 5 is true as long as the counter is less than or equal to 5. The line ((counter++)) increments the counter by 1.
2. Reading a file line by line
The canonical way to process a file line by line is:
#!/bin/bash
while IFS= read -r line
do
echo "Line: $line"
done < input.txt
Here IFS= preserves leading/trailing whitespace, and -r prevents backslash escapes from being interpreted. The file input.txt is redirected as input to the entire loop. This pattern is safe even for files without a trailing newline.
3. Infinite loop with break
Sometimes you want a loop that runs until a certain condition is met inside the body:
#!/bin/bash
while true
do
read -p "Enter a number (0 to quit): " num
if [ "$num" -eq 0 ]; then
break
fi
echo "You entered $num"
done
while true creates an infinite loop; the break statement exits it when the user enters 0.
4. Using arithmetic conditions
For numeric comparisons, you can use double parentheses (( )) directly:
#!/bin/bash
n=10
while (( n > 0 ))
do
echo "$n"
((n--))
done
This prints numbers from 10 down to 1.
Common pitfalls and how to avoid them
- Infinite loops: Forgetting to update the condition or counter. Always ensure that the condition eventually becomes false, or include a
break. - Off-by-one errors: Using
-ltinstead of-le(or vice versa) can cause one extra or one fewer iteration. Test with a small number. - Spacing in
[ ]: The brackets must have spaces around them:[ $i -lt 5 ]is correct,[$i -lt 5]is not. - Variable quoting: Always quote variables in test conditions to avoid word splitting and globbing:
[ "$var" = "yes" ]. - Changing IFS: If you modify
IFSinside a loop, it can affect other parts of the script. Save and restore it if needed.
Choosing between while, for, and until
Bash offers three main loop types:
- for: Best when you know the number of iterations or have a list of items (e.g., files, command output).
- while: Best when you want to repeat until a condition becomes false, especially when the number of iterations is unknown (e.g., reading a stream).
- until: The opposite of while – it loops as long as the condition is false. It’s less common but useful for waiting for a condition to become true.
For example, to iterate over all .txt files, a for loop is more natural:
for file in *.txt; do echo "$file"; done
But to read lines from a command output, while is preferred:
command | while read line; do echo "$line"; done
Performance and best practices
While loops in Bash are generally slower than equivalent awk or sed commands for heavy text processing, because each iteration forks a subprocess. For large files, consider using awk or sed instead. However, for scripting tasks that involve logic, while is perfectly fine.
Best practices:
- Always test your loop with a small input or a counter limit before running it on real data.
- Use
set -uto catch unset variables andset -eto exit on errors, but be aware thatset -ecan behave unexpectedly inside loops. - Prefer
[[ ... ]]over[ ... ]in Bash for more features and fewer surprises (e.g., pattern matching, no word splitting). - When reading files, use
while IFS= read -r lineto preserve content exactly.
Frequently Asked Questions
How do I loop over a range of numbers in Bash?
You can use a C-style for loop: for ((i=1; i<=10; i++)); do echo $i; done. Or use seq: for i in $(seq 1 10); do .... The C-style loop is pure Bash and faster.
How do I break out of a while loop?
Use the break statement. It exits the innermost loop. If you have nested loops and want to break out of an outer loop, you can use break 2 to break out of two levels.
What is the difference between while and until?
while runs as long as the condition is true; until runs as long as it is false. For example, until [ -f file ]; do sleep 1; done waits until a file exists.
Why is my while loop not reading the last line of a file?
If the file does not end with a newline, the read command may not process the final line. Using while IFS= read -r line usually handles this correctly because the loop still runs when the read returns a non-zero exit status but with data. However, some older Bash versions have bugs; a workaround is to append a newline to the file before processing.
Can I use a while loop to read the output of a command?
Yes, you can pipe the command output into a while loop: command | while read line; do ...; done. But note that the loop runs in a subshell, so variables set inside the loop won't be available after the pipeline. To avoid that, use process substitution: while read line; do ...; done < <(command).
How do I run a while loop in the background?
Append an ampersand & to the loop or run the whole script with &. For example: while true; do echo "running"; sleep 1; done &. You can then kill it with the job ID or PID.
Related
Formula used
in n | Number of iterations | - | 5 | 1 | 1000 out loop_count | Loop iterations executed | - | n | 0
Each line is one input (in, sel, list) or one result (out: label, unit, formula, decimals). How the calculators work
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- China’s IPv9 Decimal Network Project Explained
- Fix Wired Earbuds That Only Work in One Ear
- What to Check Before Buying the Dip in Indian Shares
- Cool Raspberry Pi Projects: 15 Ideas for Any Skill Level3
- Terraform vs Kubernetes: Key Differences
- Internet Connectivity in Remote Areas: Options0.80 USD/GB