In addition to the basic *, ? and [...] patterns, the Bash shell provides extended pattern matching operators like !(pattern-list) (‘match all except one of the given patterns’). The extglob shell option needs to be set to use them. An example:
~$ mkdir test ; cd test ; touch file1 file2 file3 ~/test$ echo * file1 file2 file3 ~/test$ shopt -s extglob # make sure extglob is set ~/test$ echo !(file2) file1 file3
If I pass a shell expression to a program which executes it in a sub-shell, the operator causes an error. Here’s a test which runs a sub-shell directly (here I’m executing from another directory to make sure expansion doesn’t happen prematurely):
~/test$ cd .. ~$ bash -c 'cd test ; echo *' file1 file2 file3 ~$ bash -c 'cd test ; echo !(file2)' # expected output: file1 file3 bash: -c: line 0: syntax error near unexpected token `(' bash: -c: line 0: `cd test ; echo !(file2)'
I’ve tried all kinds of escaping, but nothing I’ve come up with has worked correctly. I also suspected extglob is not set in a sub-shell, but that’s not the case:
~$ bash -c 'shopt -s extglob ; cd test ; echo !(file2)' bash: -c: line 0: syntax error near unexpected token `(' bash: -c: line 0: `cd test ; echo !(file2)'
Any solution appreciated!
1 Answer