Repeat while a condition holds
for walks a known list. while repeats as long as a condition command succeeds, using the same [ ] tests from lesson 8-3:
count=1 while [ "$count" -le 3 ]; do echo "lap $count" count=$((count + 1)) done
New piece: $(( )) is arithmetic expansion, the shell's calculator. $((count + 1)) evaluates to the sum. Forget the increment line and the condition never becomes false: an infinite loop. (Ctrl+C from lesson 6-2 is the escape hatch.)
A counter climbing to its limit
The variable starts at 1, the condition checks it against 3, and the body both prints and increments.
count=1 while [ "$count" -le 3 ]; do echo "lap $count" count=$((count + 1)) done echo "race over"
Output
lap 1 lap 2 lap 3 race over
The loop ends because the body changes the thing the condition tests. Once count reaches 4, the test [ "$count" -le 3 ] exits non-zero, while stops repeating, and control falls through to the final echo.
The classic: process a file line by line
read -r (from lesson 8-3) grabs one line of stdin. Put it as a while condition and redirect a file into the loop with < (lesson 5-1), and you get the standard line-by-line pattern:
while read -r name; do echo "Welcome, $name" done < guests.txt
read succeeds (exit 0) for every line and fails at end of file, which ends the loop. Every log processor, CSV importer, and batch job in shell history is built on this shape.
Greeting every line of a file
Three names go into a file, and the while-read loop handles them one line at a time.
echo "Ada" > guests.txt echo "Grace" >> guests.txt echo "Linus" >> guests.txt while read -r name; do echo "Welcome, $name" done < guests.txt
Output
Welcome, Ada Welcome, Grace Welcome, Linus
The < guests.txt at the very end is easy to overlook and essential: it attaches the file to the whole loop, not to any single command inside it, so each read pulls the next line from the same stream. Nothing in the loop mentions how many names there are, so the same code handles three guests or three thousand.
A while read -r line; do ...; done < file loop ends when read runs out of input. read returns exit code 0 for as long as lines keep arriving, and a non-zero code once it hits end of file.
Since while decides whether to continue purely from exit codes, which is lesson 8-3's idea again, that failing read is what stops the loop. The loop therefore terminates exactly when the input is exhausted, with no need to count the lines in advance.
Accumulating a running total combines a loop with arithmetic expansion. The variable total starts at 0 outside the loop, each pass adds one number to it, and the result is printed once the loop has finished.
total=0 for n in 1 2 3 4 5; do total=$((total + n)) done echo "sum: $total"
Output
sum: 15Two placement details make this correct. The accumulator is initialized before the loop, so it is not reset on every pass, and the echo comes after done, so the final sum prints once instead of five partial sums printing along the way.