
Mastering Loops in Bash Scripting
Loops are the backbone of automation in Bash scripting. Whether you’re iterating through files, processing lists, or repeating commands, loops help you write powerful and efficient scripts that scale your work.
In this guide, we’ll cover everything you need to know about looping in Bash, from basic syntax to advanced use cases, and best practices for writing clean and maintainable scripts.
Why Use Loops in Bash?
Automate repetitive tasks
Process files and directories in bulk
Execute commands multiple times with variations
Efficiently handle user input, logs, or data processing
Improve speed and reduce manual effort
Types of Loops in Bash :
1. for
Loop – Iterate Over a List
$$
for item in value1 value2 value3
do
echo “Processing $item”
done
$$
Example:
$$
for file in *.txt
do
echo “Found file: $file”
done
$$
You can also use C-style syntax (like in other programming languages):
$$
for (( i=1; i<=5; i++ ))
do
echo “Iteration $i”
done
$$
2. while
Loop – Run While a Condition is True
$$
while [ condition ]
do
#commands
done
$$
Example:
$$
count=1
while [ $count -le 5 ]
do
echo “Count is $count”
((count++))
done
$$
3. until Loop – Opposite of while
Runs until the condition becomes true.
until [ condition ]
do
#commands
done
Example:
count=1
until [ $count -gt 5 ]
do
echo “Count is $count”
((count++))
done
4. Infinite Loops
Used when you want a loop to run endlessly (until a break or kill).
$$
while true
do
echo “Running infinitely”
sleep 1
done
$$
Terminate with Ctrl + C
.
> Loop Control Statements
break
Exits the loop immediately.
$$
for i in {1..10}
do
if [ $i -eq 5 ]; then
break
fi
echo “Number: $i”
done
$$
continue
Skips the current iteration and moves to the next.
$$
for i in {1..5}
do
if [ $i -eq 3 ]; then
continue
fi
echo “Number: $i”
done
$$
> Looping Through Files and Directories:
Example: Loop through all files in a directory
$$
for file in /home/user/documents/*
do
echo “Processing file: $file”
done
$$
> Looping Through Command Output
You can loop over the output of a command using command substitution.
$$
for user in $(cut -d: -f1 /etc/passwd)
do
echo “User: $user”
done
$$
⚠️ Note: Be cautious with whitespaces. Prefer while read
loop for complex data.
> While Read Loop – Line-by-Line File Processing
$$
while read line
do
echo “Line: $line”
done < file.txt
$$
This is very effective for reading logs, CSVs, or configuration files.
> Loop with Arrays
$$
fruits=(“Apple” “Banana” “Cherry”)
for fruit in “${fruits[@]}”
do
echo “Fruit: $fruit”
done
$$
Common Mistakes in Bash Loops
1. Unquoted Variables Causing Word Splitting
When looping over variable contents, failing to quote them leads to words splitting on spaces, newlines, or special characters.
Example Mistake:
$$
for file in $my_files; do
echo “$file”
done
$$
If my_files="file one.txt file two.txt"
, it will incorrectly loop over file
, one.txt
, file
, two.txt
.
Fix:
$$
for file in “$my_files”; do
echo “$file”
done
$$
2. Incorrect for
Syntax with Globs
Beginners often forget how shell globs work in for
loops. For example:
$$
for f in *.txt
$$
If no *.txt
files exist, the loop iterates once with the literal *.txt
string instead of skipping — leading to unwanted behavior.
Tip: Use shopt -s nullglob
at the start of the script to make globs expand to nothing if no match is found.
3. Infinite Loops Due to Bad Conditions
Mistakes in while
or until
conditions can result in infinite loops:
$$
while [ $count -lt 10 ]; do
#forgot to increment count
done
$$
If count
is never incremented, the loop runs forever.
Always verify your loop modifies the variable used in the condition.
4. Confusing while
Exit Status
Using while
with commands like cat file.txt | while read line
can cause unexpected behavior because the loop runs in a subshell in many shells, so variable changes inside it don’t persist after the loop.
Use redirection instead of a pipe:
$$
while read line; do
#do something
done < file.txt
$$
5. Using continue
or break
Outside Loops
Commands like break
and continue
only make sense inside a loop. If mistakenly placed outside, they trigger errors:
$$
echo “Doing something”
continue # This will cause: ‘continue: only meaningful in a loop’
$$
6. Overwriting Loop Variables
Accidentally changing the loop variable inside the loop can lead to unexpected iterations:
$$
for item in a b c; do
item=“modified”
echo “$item”
done
$$
While sometimes intentional, it can cause confusion later in scripts relying on item
.
7. Forgetting do
or done
Bash loops require both do
and done
. Typos like:
$$
for i in 1 2 3
echo “$i”
done
$$
will produce syntax errors because do
is missing.
8. Empty Loops
Writing an empty for
or while
without any commands inside will silently succeed but do nothing, which can be a logic error.
Always include at least an echo
or placeholder comment:
$$
for i in 1 2 3; do
:
done
$$
9. Using for
Loops for Command Output Without Quoting
When looping over command output, forgetting to quote results in splitting:
$$
for line in $(cat file.txt); do
echo “$line”
done
$$
This splits words on spaces instead of reading lines.
Better approach:
$$
while IFS= read -r line; do
echo “$line”
done < file.txt
$$
10. Using Incorrect Comparison Operators in Loop Conditions
Remember: numeric comparisons use -lt
, -gt
, etc., not <
, >
, or ==
, which can produce syntax errors.
Bad:
$$
while [ $count < 5 ]; do
$$
Good:
$$
while [ $count -lt 5 ]; do
$$
Real-World Use Cases of Bash Loops
Bash loops are invaluable tools for automating repetitive tasks. Here’s how they shine in real, practical scenarios you’re likely to encounter on Linux, macOS, or even Windows (with WSL):
1. Batch File Renaming
One of the most common uses of for
loops is mass renaming files, such as appending or removing prefixes/suffixes.
Example:
$$
for f in *.jpg; do
mv “$f” “holiday_$f”
done
$$
This script renames every .jpg
file in a directory to include the holiday_
prefix — perfect for organizing photo sets.
2. Processing Log Files
System administrators often loop through log files for parsing or compression:
$$
for logfile in /var/log/*.log; do
gzip “$logfile”
done
$$
This compresses every .log
file in /var/log
, saving disk space in one go.
3. Automated Backups
Using for
or while
loops, you can back up multiple directories to a remote server or storage location:
$$
for dir in /home/user/documents /home/user/photos; do
tar -czf “$(basename $dir).tar.gz” “$dir”
done
$$
This creates compressed archives for multiple important directories.
4. Monitoring System Resources
Bash while
loops can continuously check system health — for example, alerting if memory usage gets too high:
$$
while true; do
mem=$(free | awk ‘/Mem:/ {print $3/$2 * 100.0}’)
if (( $(echo “$mem > 90.0” | bc -l) )); then
echo “Memory usage above 90%! Warning!”
fi
sleep 60
done
$$
This runs indefinitely, checking memory every minute.
5. Reading Files Line by Line
When working with config files, user lists, or data, while read
loops process files reliably:
$$
while IFS= read -r user; do
echo “Processing user: $user”
done < user_list.txt
$$
This approach prevents word splitting and preserves spaces within lines.
6. Polling Services
Operations teams use while
loops to poll whether a critical service has started, retrying until it’s up:
$$
while ! systemctl is-active –quiet nginx; do
echo “Waiting for nginx to start…”
sleep 5
done
echo “nginx is running!”
$$
This script waits until the nginx
service becomes active before continuing.
7. Automating Permissions Fixes
When a batch of files has the wrong permissions or ownership, a loop quickly corrects them:
$$
for f in /var/www/html/*; do
chmod 644 “$f”
done
$$
This ensures web files have the right read permissions.
8. Data Transformation
Loops can parse and transform data, like changing filenames or extracting information from each line of a CSV.
Example: renaming all files in a folder to lowercase:
$$
for file in *; do
newname=$(echo “$file” | tr ‘[:upper:]’ ‘[:lower:]’)
mv “$file” “$newname”
done
$$
9. Deploying to Multiple Servers
With SSH and loops, you can execute commands on a set of remote hosts:
$$
for server in server1 server2 server3; do
ssh user@$server “sudo systemctl restart app”
done
$$
This restarts a service on multiple machines — useful for clusters.
10. Repeated User Input Until Valid
You can prompt users repeatedly in scripts until they provide a valid answer:
$$
while true; do
read -p “Do you want to continue (yes/no)? ” answer
case “$answer” in
yes|y) break ;;
no|n) exit ;;
*) echo “Please answer yes or no.” ;;
esac
done
$$
This improves script interactivity and robustness.
Key Benefits of Using Loops in Real-World Scripts
✔️ Save time by automating repetitive manual work
✔️ Reduce human error in tasks like renaming, backing up, or deploying
✔️ Enable smarter, interactive scripts with conditional repetition
✔️ Handle multiple files, directories, or servers efficiently
✔️ Make your workflows scalable as tasks grow in size or complexity