Differences between revisions 3 and 9 (spanning 6 versions)
Revision 3 as of 2012-09-03 14:55:24
Size: 3136
Editor: Lhunath
Comment: dangers of global nullglob
Revision 9 as of 2015-04-03 13:22:44
Size: 132
Editor: 62-210-37-82
Comment: merged into http://mywiki.wooledge.org/glob
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
`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 [[BashFAQ/005|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.
Redirect to [[glob#nullglob]].
/* all information that this article once contained was carefully fitted into the glob article. */

Redirect to glob#nullglob.

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