Proper Iteration in Shell: Avoiding Word Splitting in For Loops
Learn safe patterns for iterating over files and data in bash. Avoid common for-loop pitfalls with word splitting and glob expansion.
Detailed Explanation
Safe Iteration Patterns in Shell Scripts
For loops are one of the most misused constructs in shell scripting. Combining them with command substitution or unquoted variables leads to subtle bugs with filenames containing spaces or special characters.
The Anti-Pattern
# BAD: Breaks on filenames with spaces
for f in $(ls /path/to/dir); do
process "$f"
done
If a file is named "my file.txt", this loop processes "my" and "file.txt" as separate items.
Safe Alternatives
Glob patterns (preferred for simple cases):
for f in /path/to/dir/*; do
[ -e "$f" ] || continue # Skip if no matches
process "$f"
done
find with while-read (for recursive searches):
while IFS= read -r -d '' file; do
process "$file"
done < <(find /path -name "*.txt" -print0)
The -print0 and -d '' combination handles all possible filenames,
including those with newlines.
Iterating Over Lines
# BAD: word splitting on spaces within lines
for line in $(cat file.txt); do
echo "$line"
done
# GOOD: read line by line
while IFS= read -r line; do
echo "$line"
done < file.txt
Iterating Over Arrays
files=("file one.txt" "file two.txt" "file three.txt")
# GOOD: iterate with quoted expansion
for f in "${files[@]}"; do
echo "$f"
done
The key is always quoting "${array[@]}" to preserve element boundaries.
Use Case
Any shell script that processes multiple files, reads lists of items, or iterates over directory contents. Backup scripts, batch processing tools, and file management automation all benefit from safe iteration patterns.
Try It — Shell Script Linter
Related Topics
SC2086: Unquoted Variable Expansion in Shell Scripts
Quoting
SC2046: Unquoted Command Substitution
Quoting
SC2002: Useless Cat — Unnecessary Use of cat in Pipelines
Anti-Patterns
SC2012: Don't Parse ls Output in Shell Scripts
Anti-Patterns
SC2006: Replace Backtick Command Substitution with $()
Deprecated Syntax