Linux Basic — Iterating Through Lists

1 minute read

Iterating Through Lists

You have arrays. You have command output. You have files in a directory. Now you need to loop over them safely — which sounds trivial, but classic shell scripts get this wrong constantly and break on filenames with spaces, newlines, or shell metacharacters.

This chapter is the cure.


What You Will Learn

By the end of this chapter you will be able to:

  • Loop over arrays with the correct quoting
  • Loop over directory entries with globs, not ls
  • Stream command output line-by-line with while read
  • Use glob patterns including ** and extglob
  • Handle arbitrary filenames with find … -print0 | xargs -0 or mapfile -d ''

Topics in This Chapter

# Topic Description
1 Looping Array Elements for x in "${arr[@]}" and index loops
2 Looping Directory Listings globs, hidden files, empty matches
3 Looping Command Output while read vs subshell pitfalls
4 Glob Patterns *, ?, […], **, extglob
5 find & xargs NUL-safe iteration for any filename
6 Practice Exercises Hands-on tasks

The Iteration Decision Tree

What am I looping over?
│
├── A Bash array       → for x in "${arr[@]}"
├── Files in cwd       → for f in *           (use a glob, never ls)
├── Recursive files    → find -print0 | mapfile -d ''   OR   shopt -s globstar; for f in **/*
├── Lines from a file  → while IFS= read -r line; do … done < file
├── Lines from a cmd   → while IFS= read -r line; do … done < <(cmd)
├── Tokens from a str  → IFS=… read -ra arr <<< "$str"
└── Numbers / range    → for ((i=0; i<n; i++)) …       OR   for i in {1..10}

Memorise these five forms and 95% of “iterate over X” questions answer themselves.


The Forbidden Idiom

# ❌ NEVER do this
for f in $(ls); do …
for f in $(find . -type f); do …

Both word-split on $IFS and glob-expand the result. Any filename with a space, tab, glob char (*, ?, [), or newline breaks the loop. Use a glob, mapfile, or find -print0.


Next → Looping Array Elements

Updated: