Loops
Repeat work with for, while and until, and process files and input line by line.
- Loop over lists, ranges, files and arguments with for
- Read input line by line with while IFS= read -r, including CSV fields
- Control loops with break and continue, and avoid the classic loop pitfalls
Loops are where scripts start saving real time. Bash has three:
1for name in Ada Grace Linus; do echo "Hi $name"; done # over a list of words
2for file in *.log; do gzip "$file"; done # over matching files
3for i in {1..5}; do echo "$i"; done # over a range
4for (( i = 0; i < 3; i++ )); do echo "$i"; done # C-style counter
5while (( fuel > 0 )); do (( fuel -= 10 )); done # while a command succeeds
6until ping -c1 relay &>/dev/null; do sleep 5; done # until a command succeedsbreak leaves the loop early; continue skips to the next round.
1for (( t = 5; t > 0; t-- )); do
2 if (( t == 3 )); then
3 echo "$t... (ignition sequence start)"
4 continue
5 fi
6 echo "$t..."
7done
8echo "Liftoff!"
9for deck in 1 2 3 4 5; do
10 [[ $deck == 4 ]] && { echo "deck $deck sealed, stopping"; break; }
11 echo "inspected deck $deck"
12done5... 4... 3... (ignition sequence start) 2... 1... Liftoff! inspected deck 1 inspected deck 2 inspected deck 3 deck 4 sealed, stopping
Reading input line by line
The idiom for processing a file or a stream one line at a time is:
while IFS= read -r line; do
echo "got: $line"
done < input.txtIFS= keeps leading and trailing spaces, -r keeps backslashes, and < input.txt feeds the whole loop. Set IFS to a delimiter to split each line into fields: while IFS=, read -r name role deck; do ... reads CSV.
1total=0
2while IFS=, read -r name role hours; do
3 [[ $name == name ]] && continue # skip the header row
4 printf '%-8s %-9s %3d h\n' "$name" "$role" "$hours"
5 (( total += hours ))
6done <<'EOF'
7name,role,hours
8ada,engineer,42
9grace,captain,38
10ken,engineer,45
11EOF
12echo "Total: $total h"ada engineer 42 h grace captain 38 h ken engineer 45 h Total: 125 h
1count=0
2printf 'a\nb\nc\n' | while read -r line; do (( count++ )); done
3echo "after a pipe: $count"
4count=0
5while read -r line; do (( count++ )); done < <(printf 'a\nb\nc\n')
6echo "after process substitution: $count"after a pipe: 0 after process substitution: 3
Key takeaways
forloops over words, files, ranges or a C-style counter;while/untilloop on a command’s status.while IFS= read -r line; do ...; done < filereads line by line; setIFS=,to split fields.breakexits,continueskips ahead.Don’t loop over
$(cat file), and remember that a pipedwhileruns in a subshell.
Lesson quiz
7 questions · pass with 5 correct · up to 50 XP
Passing this quiz completes the lesson and keeps your streak going. Questions you miss come back in review sessions later.
Practice: write Bash scripts
Write a script in the editor and run it for real against sample input. Each run gets a fresh Linux sandbox with Bash 5.2 and the GNU tools on Wandbox, a free public service - so experiment freely, even with rm. Your script and test input are sent there.
Launch countdown
stdin is a starting number N. Print N, N-1, ... down to 1, each followed by ..., then Liftoff!. If N is 0, just print Liftoff!.
- From 3
- From 0
- From 5
Your script runs with Bash 5.2 and GNU tools on Wandbox, a free public service, in a fresh sandbox each time. Your script and test input are sent to that service.
Shift report
stdin is a CSV of name,role,hours with no header. For each line print name (role): hours h, adding OVERTIME when hours are over 40. Finish with Total: N h.
ada (engineer): 42 h OVERTIME
grace (captain): 38 h
Total: 80 h- Two crew
- Night shift
Your script runs with Bash 5.2 and GNU tools on Wandbox, a free public service, in a fresh sandbox each time. Your script and test input are sent to that service.
Questions about this lesson
Stuck? Ask. Figured something out? Share it. Explaining is one of the best ways to learn.
Loading posts…