Archive for July 24th, 2008

beware of shell expansion

Thursday, July 24th, 2008

This is one of those details that will bite you if you don’t know about it and you might struggle to find the answer for something that looks like a bug.

The characters * and ? have special meaning in the shell, as you know. * means zero or more characters while ? means any character. Favorably, these glob patterns are still the same for those of us who go back to the murky days of Ms DOS.

Glob patterns are very useful in the shell, but when used with programs that themselves accept glob patters the results may be surprising. For example:

$ ls
file2.zip  file.zip
$ find -iname *.zip
find: paths must precede expression
Usage: find [-H] [-L] [-P] [path...] [expression]
$ find . -iname *.zip
find: paths must precede expression
Usage: find [-H] [-L] [-P] [path...] [expression]

Download this code: glob1

Huh? To see what’s happening here, run the shell in echo mode:

$ bash -x
$ find -iname *.zip
+ find -iname file2.zip file.zip
find: paths must precede expression
Usage: find [-H] [-L] [-P] [path...] [expression]

Download this code: glob2

So now we see what’s happening. *.zip was expanded because it matched two files in this directory. Those two files were then passed as arguments to find, not the *.zip pattern.

Bash will expand the glob pattern whether or not you use it with find, so you just have to tell it not to expand it:

$ find -iname '*.zip'
+ find -iname '*.zip'
./file2.zip
./file.zip

Download this code: glob3

This is confusing, because if *.zip doesn’t match any files, then it will be sent verbatim to the program. Therefore you should always quote your glob patterns if they are meant for a program, not the shell.