Shell Globbing#

While using the shell it often desirable to specify file names using regular expressions, for example to bulk move or rename files. Unfortunately bash does not exactly support regular expressions but a mechanism which is called globbing or path name expansion.

Path name expansion#

In the very last step before a shell command is executed, bash performs path name extension. This is quite similar to matching regular expressions against path names. However the syntax is slightly different from POSIX regular expressions. The search space consists of all file names with respect to the working directory.

Expandable expressions#

The general form of an extendable expression is given as

expr or quantifier(expr-list)

where expr and quantifier are in as the tables below and expr-list is a list of expressions separated by |.

Expandable expressions are replaced by all matching file named separated by a whitespace. For example du *.tex might be expanded to du chapter1.tex chapter2.tex tex main.tex:

[john@laptop thesis]$ ls
chapter1.aux chapter1.tex chapter2.aux chapter2.tex main.tex main.pdf

[john@laptop thesis]$ du *.tex
3123	chapter1.tex
2441	chapter2.tex
800	    main.tex

Expressions in quotes are never expanded, so du "*.tex" is executed as du "*.tex", probably resulting in an error, as the file *.tex is unlikely to exist.

[john@laptop thesis]$ du *.tex
du: cannot access '*.tex': No such file or directory

Note

Path name expansion is a quite dangerous feature as it may alter the command in unexpected ways. For example, file names starting with a - can be a misinterpreted as options. Also if the expression has no valid expansion it used unchanged and especially meta-characters can cause trouble. Even if not used explicitly, weird file names, e.g. *.tex, could cause globbing in unexpected places. Globbing can be disabled entirely (in the current session) with set -f noglob

Simple expressions#

Expression

Meaning

abc

match an actual string

[[:digit:]]

match a character in a POSIX character class

[a-f]

match a character in a character class

\?

match a meta-character

?

match a single character, except /

*

match any string of any length not containing /

Note

Globbing will never expand to hidden files by using the wildcards * or ?. This is another safety measure, commands like rm * would otherwise remove the current directory . and the parent directory ..!

Expressions with quantifiers#

Quantifier

Meaning

?

zero or one matches

*

zero or more matches

+

one or more matches

@

exactly one match

!

do not match expression from the list

Examples#

Assuming a directory structure like below.

[john@laptop ~]$ tree
.
├── bar
│   └── fileC
├── fileA
├── fileA.md
├── fileA.txt
├── fileB
├── fileB.md
├── fileB.txt
└── foo
    └── fileD

Expression

Meaning

Expansion

*

all files names

bar fileA fileA.md fileA.txt fileB fileB.md fileB.txt foo

*.txt

all file names ending in .txt

fileA.txt fileB.txt

!(fileA|*.??)

not fileA and no files with a 2 letter extension

bar fileA.txt fileB fileB.txt foo

file[[:upper:]]

all file names file followed by a single capital letter

fileA fileB

*/file[A-Z]

the same inside the every sub directory

bar/fileC foo/fileD

@(fileA|fileB.txt)

fileA or fileB.txt

fileA fileB.txt