Skip to main content
2 of 5
Better MVE data set
Chris Davies
  • 128.1k
  • 16
  • 178
  • 323

Matching negative patterns with bash extglob

Consider I have a set of seven files:

item1_data  item2_data_more  item3_data  item4_data  item5_data_more
other6_data  other7_data_more

and I want to match the three of them that do not end with more. Given that this is an example scenario you have to accept that it is not sufficient to match with the pattern item*data? (or any trivial variant).

I'm using bash with extglob enabled. For simple cases the description in the man page is sufficient ("!(pattern‐list) Matches anything except one of the given patterns"). However, here I need to achieve a match on item but a negative match for data. I finally landed on one that works but what I do not understand is why it works but others fail.

shopt -s extglob                                                # Enable extended globbing
touch {item{1,3,4},other6}_data {item{2,5},other7}_data_more    # Example data set

ls !(*more)                                                     # Non-"item" files too
item1_data  item3_data  item4_data  other6_data

ls item*!(more)                                                 # All "item" files
item1_data  item2_data_more  item3_data  item4_data  item5_data_more

ls item!(*more)                                                 # Works as required
item1_data  item3_data  item4_data

Why does the second of these fail and the third succeed? I'm thinking that the wildcard should be valid in either position - but clearly isn't. Can someone enlighten me, please.

Chris Davies
  • 128.1k
  • 16
  • 178
  • 323