Creative use of globbing syntax can do a great deal of advanced pattern matching, but in some cases we may need something more advanced, perhaps approaching regular expressions in terms of complexity. Bash's extglob feature allows us to do this. With this shopt option enabled, we can use some additional glob forms:
- ?(pattern): Match up to one occurrence of the pattern
- *(pattern): Match any number of occurrences of the pattern
- +(pattern): Match at least one occurrence of the pattern
- @(pattern): Match exactly one occurrence of the pattern
- !(pattern): Match everything except the pattern
For example, /var/log/!(*.gz) matches all files in /var/log that don't end in .gz.
Some of these are useful only when using multiple patterns separated by a pipe character, |; for example, /var/log/@(sys|mess)*.gz matches all compressed log files that start with either sys or mess.
This option can be useful, but don't use it if you can express what you need with a simple classic glob, or a set of them; we could have done the same as the previous example with /var/log/sys*.gz /var/log/mess*.gz, without needing the extglob option at all.