Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to escape extended pathname expansion patterns in quoted expressions?

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!

like image 589
akaihola Avatar asked Dec 22 '22 12:12

akaihola


2 Answers

bash parses each line before executing it, so "shopt -s extglob" won't have taken effect when bash is validating the globbing pattern syntax. The option can't be enabled on the same line. That's why the "bash -O extglob -c 'xyz'" solution (from Randy Proctor) works and is required.

like image 107
Tony Delroy Avatar answered Dec 28 '22 08:12

Tony Delroy


$ bash -O extglob -c 'echo !(file2)'
file1 file3
like image 41
Randy Proctor Avatar answered Dec 28 '22 07:12

Randy Proctor