0
$ mkdir temp && cd temp
$ ls [0-9]
ls: cannot access '[0-9]': No such file or directory
$ touch \[0-9\]
$ ls [0-9]
'[0-9]'
$ touch 1
$ ls
 1  '[0-9]'
$ ls [0-9]
1

I find this behavior very surprising. To me, the [0-9] glob pattern should only match a file whose name consists of a single numeric digit. But it is also sometimes matching a file named [0-9] itself.

Is this a bug with glob expansion in bash?

Can I disable this, so that [0-9] never matches [0-9] (as it shouldn't)?

4
7

You should set the failglob option with shopt -s failglob:

$ ls [2-9]
ls: cannot access '[2-9]': No such file or directory
$ touch '[2-9]'
$ ls [2-9]
[2-9]
$ shopt -s failglob
$ ls [2-9]
bash: no match: [2-9]

Bonus question: why did the second-to-last ls print a leading space?

Because of the new "user-friendly" default quoting style of GNU ls:

$ touch 1
$ unset QUOTING_STYLE # use the default
$ ls
 1  '[2-9]'
$ QUOTING_STYLE=literal ls
1  [2-9]
$ ls --quoting-style=literal
1  [2-9]
3

From man bash:

Pathname Expansion
  After  word  splitting,  unless  the -f option has been set, bash scans
  each word for the characters *, ?, and [.  If one of  these  characters
  appears,  then  the word is regarded as a pattern, and replaced with an
  alphabetically sorted list of filenames matching the pattern (see  Pat‐
  tern  Matching  below).   If  no  matching filenames are found, and the
  shell option nullglob is not enabled, the word is left  unchanged.

Note specifically If no matching filenames are found, and the shell option nullglob is not enabled, the word is left unchanged. That is why your initial test resulted in:

ls: cannot access '[0-9]': No such file or directory
4
  • Interesting! After reading unix.stackexchange.com/a/204944/163490 to learn the difference between nullglob (mentioned by you) and failglob (mentioned by the other answer), it looks like it is better to set failglob than nullglob to get my desired behavior, do you agree?
    – Pedro A
    Sep 27 '20 at 1:46
  • @PedroA nullglob may result in very confusing (at least for me) behaviour -- because the failing glob pattern will be completely removed (not passed as an empty argument): (t=$(mktemp -d); cd "$t"; touch foo; shopt -s nullglob; ls ba[rz]) => foo ??
    – zevzek
    Sep 27 '20 at 1:52
  • Yes, I think failglob is the way to go. The man page I quoted goes on to describe that, but since @zevzek already covered that in his answer, credit for that option goes to him. Sep 27 '20 at 2:12
  • Thank you two very much!!
    – Pedro A
    Sep 27 '20 at 5:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.