Differences between revisions 2 and 3
Revision 2 as of 2008-11-22 14:08:47
Size: 2007
Editor: localhost
Comment: converted to 1.6 markup
Revision 3 as of 2012-09-03 14:55:24
Size: 3136
Editor: Lhunath
Comment: dangers of global nullglob
Deletions are marked like this. Additions are marked like this.
Line 41: Line 41:

== Warning ==

Enabling `nullglob` on a wide scope can cause weird bugs.

For instance, `unset var[1]` will suddenly "stop working". That's because bash thinks the `var[1]` is a glob, doesn't find a file that matches it, and per instruction of `nullglob` removes it, causing your script to run `unset` instead of `unset var[1]` - and nothing gets unset.

The way to fix this issue would be to quote the variable name here: `unset 'var[1]'`. Alternatively, disable `nullglob`.

On the other hand, there is something to be said for the added benefit that `nullglob` has given you. It will help you detect cases where you're putting glob-like code in a context where those globs are interpreted without intending them to!

For example, if you didn't have `nullglob` on, and you kept your code as `unset var[$i]`, then it may get difficult to figure out a bug in your code that's causing `var1` to suddenly disappear but only when you happen to have a `var1` file in your current directory and `i` happened to be `1`. Following that rational, enabling `nullglob` in your scripts can help you write more robust code.

nullglob is a Bash shell option which affects the results of glob expansion.

Normally, when a glob which does not match any filenames is expanded, it remains unchanged. Thus, you get results like this:

  •  $ rm *.bak
     rm: cannot remove `*.bak': No such file or directory

The unmatched glob *.bak is not replaced with anything; it is passed to rm directly as if it were a literal filename. rm then tries to unlink it, and fails with a reasonable error message.

However, this causes some undesired results in programming. Consider an array populated like this:

  •  # Bash
     files=(*)
     echo "There are ${#files[*]} files here."

This fails if there are no files which match the glob -- it will report one file, because the array is loaded with the single element *.

The nullglob option lets us avoid this problem. If it is set, then an unmatched glob is swept away entirely -- replaced with a set of zero words -- instead of remaining in place as a single word.

  •  # Bash
     shopt -s nullglob
     files=(*)
     echo "There are ${#files[*]} files here."

nullglob is not on by default because there are other cases where its behavior would be extremely disconcerting. For example, ls behaves quite unexpectedly if an unmatched glob is removed from the argument list:

  •  shopt -s nullglob
     ls *.xyzqj
     # This will list all the files in the current directory
     # just as if the user had typed "ls" with no args.

nullglob by itself may not be sufficient for all cases. A glob does not, by default, match files whose names begin with a period, unless the glob itself also begins with a period. If so-called "hidden files" should also be matched by a glob, then one may wish to use the dotglob option.

  •  # Bash
     shopt -s dotglob
     shopt -s nullglob
     files=(*)
     echo "There are ${#files[*]} files here."

Just remember that these options remain in effect for the current shell process until disabled.

Warning

Enabling nullglob on a wide scope can cause weird bugs.

For instance, unset var[1] will suddenly "stop working". That's because bash thinks the var[1] is a glob, doesn't find a file that matches it, and per instruction of nullglob removes it, causing your script to run unset instead of unset var[1] - and nothing gets unset.

The way to fix this issue would be to quote the variable name here: unset 'var[1]'. Alternatively, disable nullglob.

On the other hand, there is something to be said for the added benefit that nullglob has given you. It will help you detect cases where you're putting glob-like code in a context where those globs are interpreted without intending them to!

For example, if you didn't have nullglob on, and you kept your code as unset var[$i], then it may get difficult to figure out a bug in your code that's causing var1 to suddenly disappear but only when you happen to have a var1 file in your current directory and i happened to be 1. Following that rational, enabling nullglob in your scripts can help you write more robust code.

NullGlob (last edited 2016-05-08 15:03:21 by geirha)