Bash has no feature to expand just one match out of many.
The pattern @(foo)
matches just one occurrence of the pattern foo
. That is, it matches foo
, but not foofoo
. This syntactic form is useful to build or patterns like @(foo|bar)
, which matches either foo
or bar
. It can be used as part of longer patterns like @(foo|bar)-*.txt
, which matches foo-hello.txt
, foo-42.txt
, bar-42.txt
, etc.
If you want to use one match among many, you can put the matches in an array, and then use an element of the array.
kernels=(vmlinuz*)
ls -l "${kernels[0]}"
Matches are always sorted in lexicographic order, so this will print the first match in lexicographic order.
Note that if the pattern doesn't match any file, you'll get an array containing a single element which is the unchanged pattern:
$ a=(doesnotmatchanything*)
$ ls -l "${a[0]}"
ls: cannot access doesnotmatchanything*: No such file or directory
Set the nullglob
option to get an empty array instead.
shopt -s nullglob
kernels=(vmlinuz*)
if ((${#kernels[@]} == 0)); then
echo "No kernels here"
else
echo "One of the ${#kernels[@]} kernels is ${kernels[0]}"
fi
Zsh has convenient features here. The glob qualifier [NUM]
causes the pattern to expand to only the NUMth match; the variant [NUM1,NUM2]
expands to the NUM1th through NUM2th matches (starting at 1).
% ls -l vmlinuz*([1])
lrwxrwxrwx 1 root root 26 Nov 15 21:12 vmlinuz -> vmlinuz-3.16-0.bpo.3-amd64
% ls -l nosuchfilehere*([1])
zsh: no matches found: nosuchfilehere*([1])
The glob qualifier N
causes the pattern to expand to an empty list if no file is matched.
kernels=(vmlinuz*(N))
if ((#kernels)); then
ls -l $kernels
else
echo "No kernels here"
fi
The glob qualifier om
sorts matches by increasing age instead of by name (m
is for modification time); Om
sorts by decreasing age . So vmlinuz*(om[1])
expands to the most recent kernel file.
Best Answer
The extended filename globbing pattern (supported by
bash
with theextglob
shell option activated, and also byksh93
)will ignore anything that starts with
db
.To be more specific:
This will ignore any name in the current directory that starts with exactly
db.example.com
.The
!(db.example.com)
pattern acts like a "special*
" that will not match the the stringdb.example.com
.Your pattern,
excludes any name that starts with
db
, but allows any string after that, which obviously includesdb
.By the same analogy as above,
!(db)
acts "like*
" but won't match the exact stringdb
, leaving us with the pattern**.error.log
so to speak (with the first*
being "special").