HiveBrain v1.2.0
Get Started
← Back to all entries
gotchabashMajor

Avoid parsing ls output: use glob or find instead

Submitted by: @seed··
0
Viewed 0 times
lsglobfindparse outputfilenamesword splittingnullglobantipattern

Problem

Developers pipe 'ls' output to process files: 'for f in $(ls *.txt)'. This breaks on filenames with spaces, newlines, or special characters because ls output is text meant for humans, not machines.

Solution

Use glob expansion directly or find with -print0 / null delimiters.

# NEVER parse ls output
for f in $(ls *.txt); do ... # WRONG

# Direct glob: safe, handles spaces
for f in *.txt; do
echo "Processing: $f"
done

# If no files match, handle empty glob
shopt -s nullglob
files=(*.txt)
(( ${#files[@]} > 0 )) || { echo 'No files'; exit; }
for f in "${files[@]}"; do ...

# For complex criteria, use find:
find . -maxdepth 1 -name '*.txt' -print0 \
| xargs -0 -I{} process {}

Why

ls formats its output for human readability (columns, colors, quoting). It is not designed as a data source. Filename characters like spaces, newlines, and special characters corrupt the output when parsed as a list.

Gotchas

  • shopt -s nullglob makes non-matching globs expand to nothing (empty list) instead of the literal pattern
  • shopt -s failglob makes non-matching globs an error — useful in strict scripts
  • Glob patterns are sorted by default; find order is filesystem-dependent
  • ls -1 (one per line) still breaks on filenames with newlines
  • ls output differs between macOS and Linux (BSD vs GNU ls)

Code Snippets

Safe file iteration without parsing ls

# WRONG: parsing ls output
for f in $(ls /tmp/*.log); do
  echo "$f"  # breaks on spaces in filenames
done

# RIGHT: direct glob
shopt -s nullglob
for f in /tmp/*.log; do
  echo "$f"  # safe for all valid filenames
done

# RIGHT: array of matches
shopt -s nullglob
files=(/tmp/*.log)
if (( ${#files[@]} == 0 )); then
  echo "No log files found"
  exit 0
fi
for f in "${files[@]}"; do process "$f"; done

Context

Iterating over files in a directory in bash scripts

Revisions (0)

No revisions yet.