A Bash loop can stop when a condition is met or skip an item and continue with the next one. The break and continue commands choose which of those actions Bash takes.
In this piece, I’ll compare their effects and show how a numeric level targets a loop inside another loop.
TL;DR: Choose break to exit or continue to skip
break stops the selected Bash loop, while continue skips the current pass and starts the next one. A positive number after either command targets an outer loop when loops are nested.
- Use break when no later iteration should run.
- Use continue when later items still need processing.
- In nested loops, break 2 exits two levels and continue 2 resumes the outer loop.
What Do break and continue Do in Bash?
break and continue are Bash builtins that change what happens next inside a loop. A loop repeats a body while its condition or item list allows it.
| Command | Effect | Next point |
|---|---|---|
| break | Leaves the selected loop | Command after done |
| continue | Skips the rest of this pass | Next condition or item |
| break n | Leaves n enclosing loops | After the outer selected loop |
| continue n | Skips to the nth enclosing loop’s next pass | Next condition or item |
In a for loop, continue advances to the next word or counter value. In while and until loops, Bash checks the loop condition again before another body pass.
In a while read loop, the next check attempts another read. A rejected line does not stop later lines.
When a loop reads input line by line, a condition can skip blank or irrelevant records before parsing them.
A for loop can also iterate over a shell glob such as *.log. This can exclude generated files from a batch operation.
For example, a backup script can skip files that already have a matching archive. The test should compare the current filename with the archive path, then continue before the compression command.
The Bash manual also includes select loops. These examples use for and while because they show the stop point and skipped item without adding menu input.
Put commands meant to run after the loop after done, since break skips the rest of the current body.
How to Control a Bash Loop Step by Step
Put the control command after the condition that decides whether the current item ends the loop or should be omitted. I chose a short for loop because its fixed values make both outcomes visible.
Step 1: Compare break and continue in one loop
The first loop stops before it prints 3. The second omits 3 and still prints 4.
#!/usr/bin/env bash
printf 'break: '
for n in 1 2 3 4; do
if (( n == 3 )); then break; fi
printf '%s ' "$n"
done
printf '\nafter break\n'
printf 'continue: '
for n in 1 2 3 4; do
if (( n == 3 )); then continue; fi
printf '%s ' "$n"
done
printf '\ndone\n'
The first-step output is:
break: 1 2 after break continue: 1 2 4 done

The output confirms that break leaves the loop. I placed the action after the test, so continue reaches it only when the item does not match.
Step 2: Skip a selected item in a for loop
Match the current loop variable, then place continue before the work that should not run for that item.
for name in alpha skip-me omega; do
if [[ $name == skip-me ]]; then
continue
fi
printf 'process %s\n' "$name"
done
This prints process alpha and process omega. Test the value, continue on a match, and leave the processing command below that branch.
The shell expands a glob before starting the for loop, so an an unmatched glob may remain literal depending on shell options. Check that the current item is a file before processing if an empty match set is possible.
Quote values passed to commands. For paths with spaces, iterate over a quoted array expansion such as “${files[@]}” so each path remains one value.
An unquoted expansion is split on whitespace before the loop body receives each value. The test belongs against the complete item, not one fragment of a filename.
Step 3: Use a numeric level for nested loops
A bare break leaves the inner loop, while continue 2 skips the rest of the outer pass. I checked the difference with two short nested loops.
for row in A B; do
for col in 1 2 3; do
if [[ $col == 2 ]]; then continue 2; fi
printf '%s%s ' "$row" "$col"
done
done
The continue version prints A1 B1. When col reaches 2, Bash starts the next row, so col 3 does not appear.
for row in A B; do
for col in 1 2 3; do
printf '%s%s ' "$row" "$col"
if [[ $col == 2 ]]; then break 2; fi
done
done
printf '\nafter\n'
The break version prints A1 A2, then after.
A search can use this form when an inner match ends work for one outer item but more outer items remain.
A for loop suits a known list of values. A while loop fits a condition that changes during processing, such as reading lines or retrying a command.
For a retry loop, place break after the success test and continue only when another attempt is appropriate. Also include a retry limit or timeout so a condition that never changes cannot keep the script running indefinitely.
In a while loop, update a counter before continue when the skipped branch would otherwise bypass that update. If the condition keeps seeing the same value, the loop may never finish.
A failed read ends the loop normally, so a continue branch should be reserved for lines that need no further processing.
Bash Loop Control Edge Cases
Loop-control commands depend on a positive count and the shell execution context.
A syntax error and a loop-control error are different problems. The shell parses loop structure before execution, while an invalid count is evaluated when Bash reaches the builtin.
| Case | Observed or documented behavior | Safer choice |
|---|---|---|
| continue 0 | Bash reports loop count out of range | Use a positive count |
| break outside a loop | This Bash 5.2 run printed only meaningful in a for, while, or until loop | Place it in the intended loop body |
| Function boundary | Bash 4.4 and newer reset function loop state | Return a status and decide in caller |
| Subshell boundary | A child process cannot jump to a parent loop | Test its status in the parent shell |
The continue 0 probe printed: newcomer_failure.sh: line 3: continue: 0: loop count out of range.
The break 2 command outside a loop printed: bash: line 1: break: only meaningful in a `for’, `while’, or `until’ loop.
The Bash manual notes that function loop-state behavior changed in Bash 4.4. Earlier Bash versions could let a function affect its caller loop, while newer versions reset this state. ShellCheck recommends return from a function rather than break.
I prefer a returned status because it leaves the decision in the loop body. The helper reports its result and the loop chooses whether to stop.
should_stop() {
[[ $1 == stop ]]
}
for item in keep stop later; do
if should_stop "$item"; then
break
fi
printf '%s\n' "$item"
done
A pipeline can run a while loop in a subshell. A continue command there cannot steer a loop in the parent shell.
Process substitution or input redirection can keep a while loop in the current shell in common Bash forms. Choose the input method based on whether variables set in the loop must remain available afterward.
Keep loop control beside the loop, or return a status from a child process and test it outside. This matters when input is piped into while read.
Before using break n or continue n, count the active loops enclosing the command.
Step 4: Filter a file list without losing valid paths
Use continue for a rejected path and let the loop reach every remaining path. Quoted array expansion preserves spaces, while the conditional checks both file type and the suffix before work starts.
files=("notes.txt" "draft.tmp" "meeting notes.txt")
for file in "${files[@]}"; do
[[ -f $file ]] || continue
[[ $file == *.tmp ]] && continue
printf 'keep %s\n' "$file"
done
For a directory scan, a glob can provide the list, and the same checks can reject directories or unwanted suffixes. Keep the continue branch above the command that reads or copies each accepted file.
Step 5: Use continue in a while read loop
A while read loop handles records one at a time, so continue can discard a blank or comment line while leaving later records available. Use a here-string for this small illustration so the input stays visible in the example.
while IFS= read -r line; do
[[ -z $line || $line == \#* ]] && continue
printf 'record: %s\n' "$line"
done <<< $'alpha\n\n# note\nomega'
read -r keeps backslashes in the input instead of treating them as escapes. The condition rejects the empty line and comment, then the loop prints alpha and omega. In a file-processing script, redirect a file into the loop when the loop’s variable changes must remain in the current shell.
Step 6: Troubleshoot an iteration that never advances
A continue statement can expose a loop whose state update sits later in the body. In this example the update occurs before continue, so the counter still moves when an item is skipped.
n=0
while (( n < 4 )); do
((n += 1))
if (( n == 2 )); then continue; fi
printf '%s ' "$n"
done
printf '\n'
If the increment were placed after continue, the counter would remain 2 and the condition would stay true. Move the state change before the branch or restructure the body so every path updates the value tested by while.
Use this checklist when the result surprises you:
- Confirm the command is inside the loop you intend to control.
- Check that a numeric level is positive and does not exceed the enclosing loop depth.
- Verify that the condition can change after a skipped pass.
- Check whether a pipeline moved the loop into a subshell.
Quick Reference for Bash Loop Control
Choose the command by the destination where execution should resume. This compact reference ties each form to its next location.
| Form | Use it when | Execution resumes |
|---|---|---|
| break | The current loop should end | After its done command |
| continue | The current item should be skipped | Next iteration of the current loop |
| break n | Several enclosing loops should end | After the selected outer loop |
| continue n | Skip the rest of an outer pass | Next iteration of the selected outer loop |
| return status | A helper function reports a decision | Caller chooses break or continue |
The number selects an enclosing loop level, with 1 meaning the current loop. Keep function decisions with the caller and keep the condition, state update, and control command close enough to review together.
Conclusion
Use break or continue according to the needed result, and consult the Bash manual for version-specific behavior.
For more Bash context, see our guides to while loops, for loops, if-else conditions and shell functions. The official Bash builtins manual defines both commands.
FAQ
These answers cover common loop-control questions.
How do I skip one iteration in a Bash loop?
Put continue inside a condition that matches the item. Bash skips the rest of that pass and checks the next item or loop condition.
How do I break out of two nested Bash loops?
Use break 2 inside the inner loop. It exits the inner loop and its enclosing outer loop.
Can continue skip an outer loop iteration?
Yes. continue 2 inside a nested pair skips the rest of the current outer iteration and resumes the next outer pass.
Can a Bash function use break to stop its caller’s loop?
Do not rely on that behavior. Return a status from the function and let the caller run break or continue.
