11. Bash Loops
Overview¶
Bash loops are used to execute a block of commands repeatedly. They are useful for automating repetitive tasks, processing files, iterating over lists, and executing commands until a specific condition is met.
Bash provides three commonly used loop types:
-
for— Iterates over a list of items. -
while— Repeats commands while a condition is true. -
until— Repeats commands until a condition becomes true.
Bash for Loop¶
A for loop is used to iterate over a list of values. It executes the commands inside the loop once for each item.
Syntax¶
Example: List Files and Directories¶
The following script iterates over the entries inside the /var/ directory and prints each entry.
Explanation¶
-
for item in /var/*— Assigns each entry in/var/to the variableitem. -
do— Marks the beginning of the loop body. -
echo "$item"— Displays the current entry. -
done— Marks the end of the loop.
The * wildcard expands to the entries in the directory. Unlike using ls, this approach handles filenames containing spaces more reliably.
Output¶
The exact output depends on the contents of the /var/ directory.
Running a for Loop Directly¶
A for loop can also be executed directly in the terminal without creating a script.
Example: Iterate Over Numbers¶
Output¶
Bash while Loop¶
A while loop repeatedly executes commands as long as a condition is true.
Syntax¶
Example: Countdown¶
The following script starts with a counter of 6 and decreases it by one during each iteration.
#!/bin/bash
COUNT=6
# Continue while COUNT is greater than zero
while [ "$COUNT" -gt 0 ]; do
echo "Value of count is: $COUNT"
((COUNT--))
done
Explanation¶
-
COUNT=6— Initializes the counter. -
[ "$COUNT" -gt 0 ]— Checks whetherCOUNTis greater than zero. -
echo— Displays the current counter value. -
((COUNT--))— Decreases the counter by one. -
done— Ends the loop.
The loop stops when COUNT becomes 0, because the condition is no longer true.
Output¶
Value of count is: 6
Value of count is: 5
Value of count is: 4
Value of count is: 3
Value of count is: 2
Value of count is: 1
Example: Read User Input¶
A while loop can be used to repeatedly ask the user for input.
#!/bin/bash
while true; do
read -rp "Enter a command (exit to quit): " command
if [[ "$command" == "exit" ]]; then
break
fi
echo "You entered: $command"
done
Explanation¶
-
while true— Creates a loop that continues indefinitely. -
read -rp— Reads input from the user. -
[[ "$command" == "exit" ]]— Checks whether the user enteredexit. -
break— Terminates the loop. -
Otherwise, the entered text is displayed.
Bash until Loop¶
An until loop repeatedly executes commands as long as a condition is false. It stops when the condition becomes true.
Syntax¶
Example: Count from Zero to Five¶
#!/bin/bash
COUNT=0
# Continue until COUNT becomes greater than 5
until [ "$COUNT" -gt 5 ]; do
echo "Value of count is: $COUNT"
((COUNT++))
done
Explanation¶
-
COUNT=0— Initializes the counter. -
[ "$COUNT" -gt 5 ]— Checks whether the counter is greater than five. -
until— Runs the loop while this condition is false. -
((COUNT++))— Increases the counter by one. -
The loop stops when
COUNTbecomes6.
Output¶
Value of count is: 0
Value of count is: 1
Value of count is: 2
Value of count is: 3
Value of count is: 4
Value of count is: 5
Difference Between while and until¶
| Loop | Continues when | Stops when |
|---|---|---|
while |
Condition is true | Condition becomes false |
until |
Condition is false | Condition becomes true |
Both loops can perform the same task, but they express the stopping condition differently.
Controlling a Bash Loop with Input¶
A loop can read data from standard input using the read command. This is useful when processing the output of another command, such as find.
The following example searches for files in the current directory and renames files containing spaces by replacing those spaces with underscores.
Example: Rename Files Containing Spaces¶
#!/bin/bash
# Directory to search
DIR="."
# Find regular files and process them one at a time
find "$DIR" -type f -print0 |
while IFS= read -r -d '' file; do
# Check whether the filename contains a space
if [[ "$file" == *" "* ]]; then
# Create a new filename with spaces replaced by underscores
new_file="${file// /_}"
# Rename the file
mv -- "$file" "$new_file"
echo "Renamed: $file -> $new_file"
fi
done
Explanation¶
-
DIR="."— Sets the current directory as the search location. -
find "$DIR" -type f— Searches for regular files. -
-print0— Separates filenames with a null character, allowing filenames containing spaces, tabs, and newlines to be handled safely. -
IFS= read -r -d '' file— Reads one complete filename from standard input without removing backslashes or splitting on whitespace. -
[[ "$file" == *" "* ]]— Checks whether the filename contains a space. -
${file// /_}— Replaces every space in the filename with an underscore. -
mv -- "$file" "$new_file"— Renames the file. -
done— Ends the loop.
Example Directory Before Renaming¶
Example Output¶
Renamed: ./report one.txt -> ./report_one.txt
Renamed: ./network notes.txt -> ./network_notes.txt
Renamed: ./backup file.tar -> ./backup_file.tar
Example Directory After Renaming¶
Important: Renaming files changes their names on disk. Test the script in a temporary directory before using it on important files.
Loop Control Statements¶
Bash provides statements that control how a loop executes.
break¶
The break statement immediately terminates the current loop.
Output:
continue¶
The continue statement skips the remaining commands in the current iteration and proceeds to the next iteration.
#!/bin/bash
for number in 1 2 3 4 5; do
if [ "$number" -eq 3 ]; then
continue
fi
echo "$number"
done
Output:
Useful Bash Loop Operators¶
| Operator | Meaning |
|---|---|
-gt |
Greater than |
-lt |
Less than |
-eq |
Equal to |
-ne |
Not equal to |
-ge |
Greater than or equal to |
-le |
Less than or equal to |
((COUNT++)) |
Increase the counter by one |
((COUNT--)) |
Decrease the counter by one |
break |
Exit the loop |
continue |
Skip to the next iteration |
Best Practices¶
-
Quote variables when working with filenames, such as
"$file". -
Prefer
find -print0withread -d ''when processing arbitrary filenames. -
Avoid using
for file in $(ls ...)because it can break on spaces, tabs, and newlines in filenames. -
Ensure that loop conditions eventually change when using
whileoruntil, unless an intentional infinite loop is being used. -
Use
((counter++))and((counter--))for arithmetic operations in Bash. -
Test file-manipulation scripts in a safe directory before applying them to important data.
Conclusion¶
Bash loops are essential for automation and scripting. The for loop is useful for iterating over lists and files, the while loop runs commands while a condition remains true, and the until loop continues until a condition becomes true. Combining loops with commands such as find, read, and conditional statements allows Bash scripts to process files, handle user input, and automate repetitive tasks efficiently.