Loops
Iteration constructs for repeated execution.
Source: src/scripting/control_flow.f90:274-608, src/ast/evaluator_simple_real.f90:2020-2346
For Loops
Word List Form
Iterate over a list of words:
for var in word1 word2 word3; do
echo "$var"
done
Source: control_flow.f90:359-491
Positional Parameters
When in list is omitted, iterates over $@:
for arg; do
echo "Argument: $arg"
done
Glob Expansion
Patterns are expanded to matching files:
for file in *.txt; do
echo "Processing $file"
done
# Multiple patterns
for file in *.txt *.md *.rst; do
wc -l "$file"
done
If no files match, the pattern is used literally. To avoid this:
shopt -s nullglob
for file in *.txt; do
echo "$file"
done
Brace Expansion
# Numeric range
for i in {1..5}; do
echo $i
done
# Output: 1 2 3 4 5
# With step
for i in {0..10..2}; do
echo $i
done
# Output: 0 2 4 6 8 10
# Character range
for c in {a..e}; do
echo $c
done
# Output: a b c d e
# Comma-separated
for x in {red,green,blue}; do
echo $x
done
C-Style Arithmetic Form
Source: control_flow.f90:493-608
for ((init; condition; increment)); do
commands
done
All three parts are optional:
# Standard form
for ((i=0; i<10; i++)); do
echo $i
done
# Multiple variables
for ((i=0, j=10; i<j; i++, j--)); do
echo "$i $j"
done
# Infinite loop (all parts empty)
for ((;;)); do
echo "forever"
sleep 1
done
Arithmetic expressions are evaluated via arithmetic_expansion_shell(). The initialization runs once, condition is checked before each iteration (non-zero exits), and increment runs after each iteration body.
While Loops
Source: control_flow.f90:274-314
Execute while condition is true (exit status 0):
while condition; do
commands
done
Examples
# Counter
count=0
while [[ $count -lt 5 ]]; do
echo $count
((count++))
done
# Read lines
while IFS= read -r line; do
echo "Line: $line"
done < file.txt
# Until command fails
while grep -q "busy" status.txt; do
sleep 1
done
# Infinite loop
while true; do
process_queue
sleep 5
done
Condition Re-evaluation
The condition is stored as condition_cmd on the control stack and re-evaluated fresh at each iteration. This is important for conditions that change:
while [[ $(wc -l < queue.txt) -gt 0 ]]; do
process_first_line
done
Until Loops
Source: control_flow.f90:316-357
Execute while condition is false (non-zero exit status):
until condition; do
commands
done
Semantically opposite of while. The condition is inverted internally (line 348: .not. condition_result).
# Wait for file
until [[ -f /tmp/ready ]]; do
sleep 1
done
# Equivalent while form
while [[ ! -f /tmp/ready ]]; do
sleep 1
done
Loop Control
Break
Source: src/execution/builtins.f90:2406-2456
Exit the innermost loop:
for i in {1..10}; do
if [[ $i -eq 5 ]]; then
break
fi
echo $i
done
# Output: 1 2 3 4
Exit multiple levels:
for i in {1..3}; do
for j in {1..3}; do
if [[ $j -eq 2 ]]; then
break 2 # Exit both loops
fi
echo "$i,$j"
done
done
# Output: 1,1
Continue
Source: src/execution/builtins.f90:2458-2508
Skip to next iteration:
for i in {1..5}; do
if [[ $((i % 2)) -eq 0 ]]; then
continue
fi
echo $i
done
# Output: 1 3 5
Skip multiple levels:
for i in {1..3}; do
for j in {1..3}; do
if [[ $j -eq 2 ]]; then
continue 2 # Skip to next i
fi
echo "$i,$j"
done
done
# Output: 1,1 2,1 3,1
Outside Loop Context
Both break and continue silently succeed (exit status 0) when called outside a loop, per POSIX.
Exit Status
- Loop returns exit status of last executed command
- Returns 0 if loop body never executed
Common Patterns
Process All Arguments
for file in "$@"; do
process "$file"
done
Read File Lines
while IFS= read -r line || [[ -n "$line" ]]; do
echo "$line"
done < file.txt
The || [[ -n "$line" ]] handles files without trailing newline.
Counter with While
i=0
while [[ $i -lt 10 ]]; do
echo $i
((i++))
done
Find and Process
while IFS= read -r -d '' file; do
process "$file"
done < <(find . -name "*.txt" -print0)
Retry with Backoff
attempts=0
until curl -sf http://example.com/health; do
((attempts++))
if [[ $attempts -ge 5 ]]; then
echo "Failed after 5 attempts"
exit 1
fi
sleep $((attempts * 2))
done
Menu Loop
while true; do
echo "1) Option A"
echo "2) Option B"
echo "q) Quit"
read -p "Choice: " choice
case $choice in
1) do_a ;;
2) do_b ;;
q) break ;;
*) echo "Invalid" ;;
esac
done
Nesting Limits
Control flow nesting is limited by MAX_CONTROL_DEPTH. Exceeding this limit produces: "Control flow nesting too deep" (control_flow.f90:489).