Skip to content
Loops
step 1/5

Reading — step 1 of 5

Learn

~2 min readControl Flow

Loops

Bash loops iterate over the things shells care about: words, lines, files, and number ranges. The syntax is small; the skill is choosing what to feed the loop — and one famous trap when the input is lines rather than words.

for: over a list of words

for fruit in apple banana cherry; do
    echo "I like $fruit"
done

for x in LIST walks whatever words follow in — and those words usually come from an expansion:

for f in *.txt; do          # glob: every .txt file, safely (spaces intact!)
    echo "processing $f"
done

for i in {1..5}; do         # brace expansion: 1 2 3 4 5
    echo "$i"
done

for i in $(seq 1 "$n"); do  # seq when the bound is a VARIABLE ({1..$n} does NOT expand)done

That last comment earns its place: brace ranges are expanded before variables are substituted, so {1..$n} is the literal string {1..$n} — a classic gotcha. Variable bounds want seq or the C-style form:

for (( i = 1; i <= n; i++ )); do    # C-style, arithmetic context rules apply
    total=$(( total + i ))
done

while: conditions and — crucially — lines

while (( n > 1 )); dodone

…but while's real day job in bash is reading input line by line:

while read -r line; do
    echo "got: $line"
done

This loop consumes stdin until it runs out — the pattern for processing files and piped data (-r stops backslash-mangling; write it always). It matters because the alternative people invent — for line in $(cat file) — is wrong: unquoted expansion splits on all whitespace, so lines with spaces shatter into words. Lines want while read -r; words want for. Carve that distinction in; it's the difference between a script that works and one that works on your test file.

break and continue behave as everywhere. Infinite loops are while true; do … donetrue being, in the spirit of last lesson, just a command that always succeeds.

Your exercise: Sum 1 to N

Read n, sum 1 through n, print. The accumulator, bash edition:

read n
total=0
for (( i = 1; i <= n; i++ )); do
    total=$(( total + i ))
done
echo "$total"

Same three graded details as every track (initialize before the loop; <= not <; print after) plus one bash-specific: don't reach for {1..$n} — you now know why it silently fails, and the C-style for handles variable bounds natively. Fourth language, same kata — and that's deliberate: when the pattern is muscle memory, the language differences are all you have left to learn, which is exactly the point of a fundamentals track.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…

Loops — Bash Fundamentals