Bash for loops are powerful tools in shell scripting that allow you to execute a sequence of commands repeatedly. Whether you’re automating tasks, managing files, or processing data, mastering for loops can significantly enhance your scripting capabilities. This guide will walk you through the basics of bash for loops, complete with simple examples to help you get started.
What is a For Loop?
A for loop in Bash is a control structure that repeats a block of commands for each item in a list. It’s especially useful when you need to perform the same action multiple times with different inputs.
Basic Syntax of a For Loop
The general syntax of a Bash for loop is as follows:
for VARIABLE in ITEM1 ITEM2 ITEM3 ...
do
# Commands to execute
done
- VARIABLE: A placeholder that takes the value of each item in the list, one at a time.
- ITEM1 ITEM2 ITEM3 …: The list of items you want to iterate over.
- do … done: The block of commands that will be executed for each item.
Simple Example: Iterating Over a List of Words
Let’s start with a basic example where we print each word in a list.
#!/bin/bash
# Define a list of fruits
fruits="Apple Banana Cherry"
# For loop to iterate over each fruit
for fruit in $fruits
do
echo "I like $fruit"
done
Explanation:
- Define the List: We create a variable
fruits
containing three items: Apple, Banana, and Cherry. - For Loop: The loop iterates over each fruit in the
fruits
list. - Echo Statement: For each iteration, it prints “I like [Fruit]”.
Output:
I like Apple
I like Banana
I like Cherry
Example 2: Iterating Over a Range of Numbers
Bash allows you to loop through a sequence of numbers using brace expansion.
#!/bin/bash
# For loop to iterate from 1 to 5
for number in {1..5}
do
echo "Number: $number"
done
Explanation:
- Range:
{1..5}
generates numbers from 1 to 5. - For Loop: Iterates over each number in the range.
- Echo Statement: Prints “Number: [Number]” for each iteration.
Output:
Number: 1
Number: 2
Number: 3
Number: 4
Number: 5
Example 3: Using a For Loop with Command Output
You can use the output of a command as the list for the loop. For example, listing files in a directory.
#!/bin/bash
# For loop to iterate over each file in the current directory
for file in $(ls)
do
echo "File: $file"
done
Explanation:
- Command Substitution:
$(ls)
executes thels
command, listing all files in the current directory. - For Loop: Iterates over each file name returned by
ls
. - Echo Statement: Prints “File: [File Name]” for each file.
Output:
File: document.txt
File: script.sh
File: image.png
...
Note: Using ls
in scripts can sometimes lead to issues with file names containing spaces or special characters. For more robust scripts, consider using globbing (e.g., for file in *
).
Example 4: Looping Through Files with a Specific Extension
Suppose you want to perform an action on all .txt
files in a directory.
#!/bin/bash
# For loop to iterate over all .txt files
for file in *.txt
do
echo "Processing $file..."
# Example command: Display the first line of each file
head -n 1 "$file"
done
Explanation:
- Globbing:
*.txt
matches all files ending with.txt
in the current directory. - For Loop: Iterates over each
.txt
file. - Echo Statement: Prints “Processing [File Name]…”.
- Head Command: Displays the first line of each file.
Sample Output:
Processing notes.txt...
Welcome to my notes.
Processing report.txt...
Executive Summary
Processing data.txt...
ID, Name, Age
Example 5: Nested For Loops
Sometimes, you may need to use a for loop within another for loop. For example, iterating over a list of directories and then over files within each directory.
#!/bin/bash
# Define a list of directories
directories="Documents Downloads Pictures"
# Outer loop: Iterate over each directory
for dir in $directories
do
echo "Directory: $dir"
# Inner loop: Iterate over each file in the directory
for file in "$dir"/*
do
echo " File: $(basename "$file")"
done
done
Explanation:
- Outer Loop: Iterates over each directory in the
directories
list. - Echo Statement: Prints the directory name.
- Inner Loop: Iterates over each file within the current directory.
- Echo Statement: Prints the file name, indented for clarity.
Sample Output:
Directory: Documents
File: resume.pdf
File: project.docx
Directory: Downloads
File: setup.exe
File: movie.mkv
Directory: Pictures
File: photo1.jpg
File: photo2.png
Common Mistakes to Avoid
- Missing
done
: Always end your for loop withdone
. Forgetting this will result in a syntax error.
for i in {1..3}
do
echo "Number: $i"
# Missing 'done' here
- Incorrect Variable Usage: Variables inside the loop should be referenced with a
$
.
for i in {1..3}
do
echo "Number: $i" # Correct
echo "Number: i" # Incorrect, prints 'i' literally
done
- Spaces Around
=
in Variable Assignment: When assigning values to variables, avoid spaces around=
.
name="John" # Correct
name = "John" # Incorrect
- Using Quotes Properly: When dealing with filenames or strings that may contain spaces, use quotes to prevent word splitting.
for file in *.txt
do
echo "Processing '$file'"
done
Tips for Effective Use of For Loops
- Use Meaningful Variable Names: Choose variable names that clearly indicate what they represent.
for filename in *.log
do
echo "Archiving $filename"
done
- Combine With Other Control Structures: For loops can be combined with
if
statements,case
statements, and other loops for more complex scripts.
for file in *.sh
do
if [[ -x "$file" ]]; then
echo "$file is executable."
else
echo "$file is not executable."
fi
done
- Use Brace Expansion for Simple Ranges: When iterating over a simple numeric range, brace expansion is concise and efficient.
for i in {10..1..-1}
do
echo "Countdown: $i"
done
- Leverage Command Substitution Carefully: Be cautious when using command substitution to avoid unexpected word splitting. Use quotes when necessary.
for user in "$(cut -d: -f1 /etc/passwd)"
do
echo "User: $user"
done
Note: The above example might not work as intended due to word splitting. Instead, use a while loop with read
for safer handling.
Conclusion
Bash for loops are essential for automating repetitive tasks and managing data efficiently in shell scripts. By understanding the basic syntax and practicing with simple examples, you can leverage for loops to enhance your scripting skills. Remember to pay attention to syntax details and practice writing your own loops to become more comfortable with their usage.
Practice Exercise
Task: Write a Bash script using a for loop that creates backup copies of all .conf
files in the current directory by appending .bak
to each filename.
Example:
- Original file:
settings.conf
- Backup file:
settings.conf.bak
Solution:
#!/bin/bash
# Iterate over all .conf files
for file in *.conf
do
# Create a backup by copying the file with .bak extension
cp "$file" "$file.bak"
echo "Backup created for $file as $file.bak"
done
Explanation:
- Loop Through
.conf
Files: The loop goes through each file ending with.conf
. - Copy Command:
cp
creates a copy of the file with.bak
appended to its name. - Echo Statement: Confirms the creation of each backup.
Running the Script:
Save the script as backup.sh
, make it executable, and run it:
chmod +x backup.sh
./backup.sh
Expected Output:
Backup created for settings.conf as settings.conf.bak
Backup created for database.conf as database.conf.bak
...