Home > OS >  Why isn't nullglob behaviour default in Bash?
Why isn't nullglob behaviour default in Bash?

Time:12-02

I recently needed to use a Bash for loop to recurse through a few files in a directory:

for video in **/*.{mkv,mp4,webm}; do
  echo "$video"
done

After way too much time spent debugging, I realised that the loop was run even when the pattern didn't match, resulting in:

file1.mkv
file2.mp4
**/*.webm # literal pattern printed when no .webm files can be found

Some detailed searching eventually revealed that this is known behaviour in Bash, for which enabling the shell's nullglob option with shopt -s nullglob is intended to be the solution.

Is there a reason that this counter-intuitive behaviour is the default and needs to be explicitly disabled with nullglob, instead of the other way around? Or to put the question another way, are there any disadvantages to always having nullglob enabled?

CodePudding user response:

From man 7 glob:

Empty lists

The nice and simple rule given above: "expand a wildcard pattern into the list of matching pathnames" was the original UNIX definition. It allowed one to have patterns that expand into an empty list, as in

xv -wait 0 *.gif *.jpg

where perhaps no *.gif files are present (and this is not an error). However, POSIX requires that a wildcard pattern is left unchanged when it is syntactically incorrect, or the list of matching pathnames is empty. With bash one can force the classical behavior using this command:

shopt -s nullglob

(Similar problems occur elsewhere. For example, where old scripts have

rm `find . -name "*~"`

new scripts require

rm -f nosuchfile `find . -name "*~"`

to avoid error messages from rm called with an empty argument list.)

In short, it is the behavior required to be POSIX compatible.

Granted though, you can now ask what the rationale for POSIX was to specify that behavior. See this unix.stackexchange.com question for some reasons/history.

  • Related