16

Using the pattern match !("file1") does not work within a bash script but will work on the command line.

For example:

ls  !("file1"|"file2")

This will list all files in directory except file1 and file2.

When that line is executed in a script this error is displayed:

./script.sh: line 1: syntax error near unexpected token `('
./script.sh: line 1: ` ls  !("file1"|"file2") ' 

Regardless what is used rm -v !("file1"). The same error takes place. What is going on here why does this not work in a script?

James Brown
  • 36,089
  • 7
  • 43
  • 59
Ogden
  • 171
  • 5
  • 1
    Possible duplicate of [How can I use inverse or negative wildcards when pattern matching in a unix/linux shell?](https://stackoverflow.com/q/216995/608639), [List all files that do not match pattern using ls](https://stackoverflow.com/q/12634013/608639), etc. And related is [Why would I not leave extglob enabled in bash?](https://stackoverflow.com/q/17191622/608639) – jww Apr 06 '19 at 13:23
  • run it using `source script.sh` – blasrodri Jun 13 '20 at 11:40

3 Answers3

17

The extended glob syntax you are trying to use is turned off by default; you have to enable it separately in each script where you want to use it.

shopt -s extglob

Scripts should not use ls though I imagine you were using it merely as a placeholder here.

tripleee
  • 175,061
  • 34
  • 275
  • 318
5

Globbing doesn't work that way unless you enable extglob shell opt. Instead, I recommend using find:

find . -maxdepth 1 -not -name '<NAME>' -or -name '<NAME>' -delete

before running this command with -delete ensure the output is correct

Rafael
  • 7,605
  • 13
  • 31
  • 46
3

Method with default settings and no external procs:

for f in *; do [[ $f =~ ^file[12]$ ]] || echo "$f"; done
vintnes
  • 2,014
  • 7
  • 16