Size: 3136
Comment: dangers of global nullglob
|
Size: 132
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.