In their simplest form, globs are wildcards. That is, *
matches zero or more characters.
$ touch {a,b,c}.txt {x,y,z}.md
$ ls *.txt
a.txt b.txt c.txt
If the globstar
shell option is enabled, globs can recursively match the contents of
subdirectories in a filename expansion context.
$ shopt -s globstar
$ mkdir -p a/b/c/
$ touch a/a.txt a/b/b.txt a/b/c/c.txt
$ ls **/*.txt
a/a.txt a/b/b.txt a/b/c/c.txt
You may also use ?
to match single characters
$ touch a.txt .a.txt.swp .a.txt.swo the.swarm.mp4
$ shopt -s dotglob
$ ls *.sw*
.a.txt.swo .a.txt.swp the.swarm.mp4
$ ls *.sw?
.a.txt.swo .a.txt.swp
Yes, it's a strained example.
There are also character range expressions that look like [a-z0-9]
or similar. Note that
they're highly locale dependent, so it may be a good idea to enable the
globasciiranges
shell option to force the use of the C locale. Similar to regular
expressions, you can negate range expressions with a !
or a ^
as the first
character inside the square brackets.
$ touch {a,b,c,d,e,f,g,h,i}.txt
$ ls [^a-f]*.txt
g.txt h.txt i.txt
$ ls [[:xdigit:]].txt
a.txt b.txt c.txt d.txt e.txt f.txt
$ ls [:xdigit:].txt
d.txt g.txt i.txt
Pay attention to the last example. The character classes must be inside double square brackets.
You may set the GLOBIGNORE
environment variable to a colon-separated list of glob patterns
to ignore.
$ touch {a,b,c,d}.txt
$ GLOBIGNORE="d.txt" ls *.txt
a.txt b.txt c.txt d.txt
$ GLOBIGNORE="d.txt"
$ ls *.txt
a.txt b.txt c.txt
$ unset GLOBIGNORE
It appears as though you must set the variable before invoking a command. I think this is
because the glob is expanded first, and then ls
is
execve(2)
'd with the expanded arguments, at which time the GLOBIGNORE
variable is evaluated.
You could also do ( GLOBIGNORE="d.txt"; ls *.txt )
so that you don't have to remember
to unset GLOBIGNORE
afterwards.
Because GLOBIGNORE
must be set before the glob is evaluated, you may prefer to extended
pattern matching by enabling the extglob
shell option.
$ touch {a,b,c,d}.txt
$ shopt -s extglob
$ ls !(d).txt
a.txt b.txt c.txt
The extglob
option enables the following extended pattern matching operators.
!(pattern1|pattern2|...)
matches everything except the given patterns@(pattern1|pattern2|...)
matches one of the given patternss?(pattern1|pattern2|...)
matches zero or one of the given patternss+(pattern1|pattern2|...)
matches one or more of the given patterns*(pattern1|pattern2|...)
matches zero or more of the given patterns$ touch {a,b,c,d}.txt {aa,bb,cc,dd}.md
$ ls *.!(md)
a.txt b.txt c.txt d.txt
$ ls @(a|b).*
a.txt b.txt
$ ls +(a|b).*
aa.md a.txt bb.md b.txt
There are several other glob-related shell options:
nocaseglob
- make filename matching case-insensitivenullglob
- allow patterns that match nothing to expand to a null string, rather than
themselves
failglob
- patterns that fail to match filenames result in an expansion error