VMware ESXi and vSphere Cluster Management
Linux Shell while Loops
Learn how to write Linux shell while loops, test conditions, update counters, prevent infinite loops, and choose between while, until, and for.
A while loop is a shell control structure for running the same command block repeatedly while a condition succeeds. The shell evaluates the condition before every iteration. If the test succeeds, the loop body runs; when the test becomes false, execution stops and continues after done.
While loops are useful when repetition depends on a changing condition, such as waiting for a file, reading input until the end of a stream, or counting until a limit is reached.
Basic while Loop Syntax
A multiline shell while loop has this structure:
while [ condition ]
do
commands
done
The usual formatting does not include an extra space before done; the complete form is:
while [ condition ]
do
commands
done
while begins the loop. The condition is a command or test whose exit status determines whether the body runs. do begins the repeated command block, and done closes it.
| Component | Role | Example |
|---|---|---|
while | Starts a loop that continues while its test succeeds. | while |
| Condition or test | Determines whether another iteration is allowed. | [ "$NUM" -lt 5 ] |
do | Begins the loop body. | do |
| Loop body commands | Commands repeated on each successful test. | echo "$NUM" |
done | Ends the loop body. | done |
In an interactive shell, semicolons can separate parts of a loop on one line:
while [ "$NUM" -lt 5 ]; do echo "$NUM"; let NUM=NUM+1; done
In a script, the multiline form is usually easier to read.
Conditions and the test Command
The syntax [ ... ] is the shell's test command written in a bracket form. It evaluates a comparison or another condition and returns an exit status. An exit status is the numeric result returned by a command. In shell scripting, status zero generally means success, while a nonzero status means failure.
A while loop runs its body when the condition command returns status zero. For example:
while [ "$NUM" -lt 5 ]
do
echo "$NUM"
done
Here, the test succeeds when NUM is numerically less than five. The body runs only after a successful test. Once the test fails, the shell skips the body and moves past done.
Spaces are required around the opening and closing brackets and between the test operands. The brackets are command arguments, not punctuation that can be attached to other text. This is valid:
[ "$NUM" -lt 5 ]
This is invalid because the required spaces are missing:
[$NUM -lt 5]
Numeric Test Operators
Numeric comparison operators compare integer values. Do not use the string comparison operators when you intend to compare numbers.
| Operator | Meaning | Example condition |
|---|---|---|
-lt | Numerically less than | [ "$NUM" -lt 5 ] |
-le | Numerically less than or equal to | [ "$NUM" -le 5 ] |
-eq | Numerically equal to | [ "$NUM" -eq 5 ] |
-ne | Numerically not equal to | [ "$NUM" -ne 5 ] |
-gt | Numerically greater than | [ "$NUM" -gt 5 ] |
-ge | Numerically greater than or equal to | [ "$NUM" -ge 5 ] |
Variables in Loop Conditions
Initialize a loop variable before entering a count-controlled loop. Shell assignment has no spaces around the equals sign:
NUM=0
When reading the variable's value, use the dollar sign for variable expansion. Expansion replaces a reference such as $NUM with its current value:
echo "$NUM"
[ "$NUM" -lt 5 ]
These two forms have different purposes:
NUM=0assigns a value to the variable.$NUMexpands the variable to its current value."$NUM"expands it while preserving it as one argument, including when the value is empty or contains whitespace.
A count-controlled loop must change the controlling variable inside the body. If NUM remains zero, a condition such as [ "$NUM" -lt 5 ] remains true forever.
Arithmetic Updates
The loop needs an arithmetic update on every iteration so that the condition can eventually become false. The following example uses let, an arithmetic builtin supported by Bash and Korn shell:
NUM=0
while [ "$NUM" -lt 5 ]
do
echo "The number is $NUM."
let NUM=NUM+1
done
Modern Bash and Korn shell code commonly uses arithmetic syntax instead:
count=0
while [ "$count" -lt 3 ]
do
printf 'Pass %s\n' "$count"
((count++))
done
((count++)) increments the numeric variable after the command is evaluated. Another form uses arithmetic expansion and assignment:
NUM=$((NUM + 1))
Arithmetic expansion is suitable for many POSIX-style shell scripts. The let and (( ... )) forms are shell-specific arithmetic features, so execute them with a compatible interpreter such as Bash when required.
Reading a Counting Loop
Consider this complete loop:
NUM=0
while [ "$NUM" -lt 5 ]
do
echo "The number is $NUM."
let NUM=NUM+1
done
Its sequence is:
- Set
NUMto zero. - Test whether
NUMis less than five. - Print the current value.
- Increase
NUMby one. - Return to the condition test.
The output values are 0, 1, 2, 3, and 4. A less-than test with an upper bound of five excludes five itself. After printing four, the increment changes NUM to five. The next test, [ 5 -lt 5 ], fails, so the body does not run again.
Condition-Driven Example: Wait for a File
A while loop does not have to count. It can repeatedly check external state:
while [ ! -f /tmp/ready.flag ]
do
echo "Waiting for ready.flag"
sleep 1
done
echo "File detected"
The -f test succeeds when the path is a regular file. The exclamation mark negates the test, so the loop continues while the file does not exist. Once /tmp/ready.flag appears, the condition becomes false and the script prints File detected.
Loop Safety and Termination
An infinite loop is a loop that does not terminate because its continuation condition never becomes false. Before running a loop, identify what can make its condition fail.
- For a counter loop, verify that every iteration changes the counter toward the limit.
- For a file or process check, verify that the external state can eventually change.
- Use a small bound while testing.
- Print diagnostic values temporarily so you can observe the condition-dependent state.
- Use a delay such as
sleep 1when polling external state, rather than checking continuously.
If an accidentally endless foreground script is running, press Ctrl+C to send an interrupt and stop it.
Running a Shell Script
Save a loop in a script file and run it with an interpreter that supports its syntax. For Bash-compatible code:
bash script.sh
Using the intended interpreter matters. Arithmetic syntax may work in Bash but fail when the script is executed by a different shell. If portability is important, choose syntax supported by the target shell and test the script in that environment.
while, until, and for Loops
Shell loop constructs differ mainly in how they decide whether another iteration should run.
| Loop type | Runs when | Best use case |
|---|---|---|
while | The test succeeds. | A condition remains true, such as a file not yet existing or a counter being below a limit. |
until | The test fails. | Repeat work until a condition succeeds. |
for | There is another item in a list, range, or other sequence. | Iterate through a known collection or fixed set of values. |
Choose a while loop when the stopping decision depends on a condition that is checked before each iteration. A for loop is often clearer when the items or number of iterations are already known. An until loop can make code more readable when the natural description is “keep going until this test succeeds.”
Troubleshooting while Loops
Syntax error near [ or do
A common cause is missing spaces in the test, such as [$NUM -lt 5], or a missing separator before do in a one-line loop. Use the canonical multiline structure or separate one-line components with semicolons:
while [ "$NUM" -lt 5 ]; do
echo "$NUM"
NUM=$((NUM + 1))
done
The loop never stops
The counter may not be incremented, the update may affect a different variable, or the condition may be impossible to make false. Display the controlling value in the loop and confirm that it moves toward the boundary. Stop a running foreground loop with Ctrl+C.
Integer-expression error
The variable may be empty or contain nonnumeric text. Initialize it to a valid integer and quote its expansion in the test:
NUM=0
while [ "$NUM" -lt 5 ]
One extra or one fewer iteration
Trace the initial value, condition, body, and update in that order. Use -lt for an exclusive upper bound, so values below five are selected. Use -le when the boundary value itself should be included. Also check whether the counter is updated before output instead of after output.
Arithmetic syntax differs between shells
Some arithmetic forms are Bash or Korn shell features. Run Bash-compatible code with bash script.sh, or use arithmetic expansion when the target shell supports it and portability is required.