koalaman edited this page Jan 20, 2018 · 2 revisions

Iterating over ls output is fragile. Use globs.

Problematic code:

for f in $(ls *.wav)
do
  echo "$f"
done

Correct code:

for f in *.wav
do
  [[ -e $f ]] || break  # handle the case of no *.wav files
  echo "$f"
done

Also note that in Bash, shopt -s nullglob will allow the loop to run 0 times instead of 1 if there are no matches. There are also several other conditions to be aware of.

Rationale:

When looping over a set of files, it's always better to use globs when possible. Using command expansion causes word splitting and glob expansion, which will cause problems for certain filenames (typically first seen when trying to process a file with spaces in the name).

The following files can or will break the first loop:

touch 'filename with spaces.wav'
touch 'filename with * globs.wav'
touch 'More_Globs[2003].wav'
touch 'files_with_fønny_chæracters_in_certain_locales.wav'

Related resources:

ShellCheck

Clone this wiki locally
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.