Search code examples
bashglob

bash: Problems with glob negation and multiple patterns


I am trying to write a glob pattern that returns a list of files that do not end in one of 2 possible suffixes: done and monthly

The list of files in my test directory is:

foo.done
foo.montly
foo.pdf
foo.txt

I am perfectly successful if I perform negation for only 1 suffix:

ls  !(*done) or ls  !(*monthly)

However, when I tried something like this:

ls  !({*monthly,*done})

I get this:

foo.done
foo.monthly
foo.pdf
foo.pdf
foo.txt
foo.txt

Can someone help me understand a result that not only doesn't produce what I want in terms of negation but also lists duplicates!


Solution

  • Use | to separate the patterns in the pattern list (docs):

    If the extglob shell option is enabled using the shopt builtin, several extended pattern matching operators are recognized. In the following description, a pattern-list is a list of one or more patterns separated by a ‘|’.

    Result:

    $ shopt -s extglob
    
    $ ls
    foo.done  foo.monthly  foo.pdf  foo.txt
    
    $ ls *.!(monthly|done)
    foo.pdf  foo.txt