In bash, I can use a negative wildcard to glob all files in a directory that don't match some pattern, for example:
echo src/main/webapp/!(WEB-INF)
This works fine.
However, if I try to use exactly the same wildcard with bash -c
to pass the command as an argument to a new bash shell, I get a syntax error:
$ bash -c 'echo src/main/webapp/!(WEB-INF)'
bash: -c: line 0: syntax error near unexpected token `('
bash: -c: line 0: `echo src/main/webapp/!(WEB-INF)'
Note that if I use a different glob, like bash -c 'echo src/main/webapp/*'
it works as expected.
Why doesn't bash accept the same negative glob with -c
as it does when run normally, and how can I get it to accept this negative glob?
That's because !(..)
is a extended glob pattern that is turned on by default in your interactive bash shell, but in an explicit sub-shell launched with -c
, the option is turned off. You can see that
$ shopt | grep extglob
extglob on
$ bash -c 'shopt | grep extglob'
extglob off
One way to turn on the option explicitly in command line would be to use the -O
flag followed by the option to be turned on
$ bash -O extglob -c 'shopt | grep extglob'
extglob on
See extglob on Greg's Wiki for the list of extended glob patterns supported and The Shopt Builtin for a list of the extended shell options and which ones are enabled by default.