Bash by Example: For Loop
Detailed look at the for loop syntax and usage patterns, iterating over explicit lists of values, using brace expansion for numeric and character ranges, processing command output with command substitution, understanding whitespace splitting behavior, and implementing C-style for loops with initialization and increment expressions.
Code
#!/bin/bash
# Iterate over a list of strings
echo "--- List ---"
for color in Red Green Blue; do
echo "Color: $color"
done
# Iterate over a range (brace expansion)
echo -e "\n--- Range ---"
for i in {1..5}; do
echo "Number: $i"
done
# Iterate over command output (Command Substitution)
echo -e "\n--- Command Output ---"
# Note: This splits by whitespace, so filenames with spaces will break!
for file in $(ls *.txt 2>/dev/null); do
echo "Found file: $file"
done
# C-style for loop
echo -e "\n--- C-Style ---"
for ((i=0; i<3; i++)); do
echo "Index: $i"
doneExplanation
The for loop is one of the most versatile control structures in Bash. Its most common form, for var in list, iterates over a sequence of words. This list can be explicit strings, a variable expansion, or the result of a command substitution.
Bash also supports brace expansion {start..end} to generate sequences of numbers or characters. This is efficient and readable for fixed ranges. For dynamic numeric ranges or C-programmers, the C-style syntax for ((init; cond; step)) is available.
A common pitfall is iterating over command output like $(ls). Because the for loop splits input by whitespace (spaces, tabs, newlines), filenames containing spaces will be treated as multiple items. For file iteration, using glob patterns directly (e.g., for f in *.txt) is much safer.
Code Breakdown
color takes on each value in the list "Red", "Green", "Blue" sequentially.{1..5} generates "1 2 3 4 5". This happens before the loop starts.$(ls). While common, this is risky for filenames with spaces. Use for file in *.txt instead for robustness.
