Is there an easy way to set nullglob for one glob

With mapfile in Bash 4, you can load an array from a subshell with something like: mapfile array < <(shopt -s nullglob; for f in ./*; do echo "$f"; done). Full example:

$ shopt nullglob
nullglob        off
$ find
.
./bar baz
./qux quux
$ mapfile array < <(shopt -s nullglob; for f in ./*; do echo "$f"; done)
$ shopt nullglob
nullglob        off
$ echo ${#array[@]}
2
$ echo ${array[0]}
bar baz
$ echo ${array[1]}
qux quux
$ rm *
$ mapfile array < <(shopt -s nullglob; for f in ./*; do echo "$f"; done)
$ echo ${#array[@]}
0
  • Be sure to glob with ./* instead of a bare * when using echo to print the file name
  • Doesn't work with newline characters in the filename :( as pointed out by derobert

If you need to handle newlines in the filename, you will have to do the much more verbose:

array=()
while read -r -d $'\0'; do
    array+=("$REPLY")
done < <(shopt -s nullglob; for f in ./*; do printf "$f\0"; done)

But by this point, it may be simpler to follow the advice of one of the other answers.


This is just a tiny bit better than your original suggestion:

local nullglob=$(shopt -p nullglob) ; shopt -s nullglob

... do whatever you want ...

$nullglob ; unset nullglob

Unset it when done:

shopt -u nullglob

And properly (i.e. storing the previous state):

shopt -u | grep -q nullglob && changed=true && shopt -s nullglob
... do whatever you want ...
[ $changed ] && shopt -u nullglob; unset changed

Tags:

Bash

Glob

Shopt