Linux and Bash course menu
Bash Loops: for, while and until with Examples
Automate repetition in Bash with for and while loops, loop over files and command output, read a file line by line, and use break and continue.
On this page
for#
A for loop runs once for each item in a list:
for city in Hyderabad Pune Chennai; do
echo "Office: $city"
doneOffice: Hyderabad
Office: Pune
Office: ChennaiNumber ranges use braces, or the C-style form:
for i in {1..3}; do
echo "Try $i"
done
for ((i = 0; i < 6; i += 2)); do
echo "$i"
doneTry 1
Try 2
Try 3
0
2
4Looping over files#
Use a wildcard directly, and quote the variable, so that names with spaces work:
mkdir photos
touch "photos/beach day.jpg" photos/party.jpg
for file in photos/*.jpg; do
echo "Found: $file"
doneFound: photos/beach day.jpg
Found: photos/party.jpgA common job is renaming files:
touch a.txt b.txt
for f in *.txt; do
mv "$f" "${f%.txt}.md"
done
ls *.mda.md
b.md${f%.txt} removes .txt from the end. See string handling.
while#
while repeats as long as its condition succeeds:
count=3
while (( count > 0 )); do
echo "$count..."
((count--))
done
echo "Go"3...
2...
1...
GoRead a file line by line#
This is the correct way to process a file:
printf 'asha,admin\nravi,user\n' > users.csv
while IFS=, read -r name role; do
echo "$name has role $role"
done < users.csvasha has role admin
ravi has role userIFS=, splits each line on commas, and -r keeps backslashes as they are. The file is fed in with < users.csv at the end of the loop.
To process a command's output, use a pipe, or < <(command):
total=0
while read -r size; do
((total += size))
done < <(printf '10\n20\n30\n')
echo "Total: $total"Total: 60With a plain pipe, the loop runs in a subshell, and total would be lost when it ends.
until#
until is the opposite of while. It runs until the condition succeeds, which suits waiting for something:
tries=0
until [[ -f ready.txt ]]; do
((tries++))
(( tries == 2 )) && touch ready.txt
done
echo "Ready after $tries tries"Ready after 2 triesbreak and continue#
break leaves the loop, and continue moves to the next item:
for n in 1 2 3 4 5 6; do
(( n == 5 )) && break
(( n % 2 == 0 )) && continue
echo "$n"
done1
3Retry a command#
This pattern is useful in deployment scripts:
attempt=1
until false || (( attempt == 3 )); do
echo "Attempt $attempt failed, retrying"
((attempt++))
sleep 0.1
done
echo "Giving up after $attempt"Attempt 1 failed, retrying
Attempt 2 failed, retrying
Giving up after 3Replace false with a real command, such as curl -sf http://localhost:8000/health.
Common mistakes#
Practice#
Practice exercise
Use a loop to create log1.txt, log2.txt and log3.txt, each containing its own number, then print the total of all the numbers by reading the files in a second loop.
Show solution
for i in 1 2 3; do
echo "$i" > "log$i.txt"
done
sum=0
for f in log*.txt; do
((sum += $(cat "$f")))
done
echo "Sum: $sum"Sum: 6Key takeaway#
Next: Functions.
Finished this lesson?