Table of Contents
Wildcards and globbing let you use patterns instead of typing exact filenames on the command line. The shell expands these patterns before running the command, turning them into a list of matching paths.
This chapter focuses on how to write and use those patterns.
What “globbing” means
- Globbing: the shell’s process of expanding wildcard patterns (like
*.txt) into matching filenames. - It happens in the shell, not in the command.
- Commands like
ls,rm,cpdon’t understand*directly; the shell replaces the pattern with matching paths, then runs the command.
Example:
- You type:
rm *.log - Shell expands
*.logto:rm app.log old.log error.log - Then
rmsees each filename separately.
If a pattern matches nothing, behavior depends on the shell and settings (more on that later).
Basic wildcards
`*` — match “anything”
* matches zero or more characters (except /).
Common uses:
*— all non-hidden files in current directory*.txt— any name ending with.txtfile*— any name starting withfilefile— any name containingfile
Examples:
# List all .txt files
ls *.txt
# Copy all JPEG photos
cp *.jpg *.jpeg ~/Pictures/
# Remove all .log files in current directory
rm *.log
Remember: * does not cross directory boundaries; it won’t match /.
`?` — match a single character
? matches exactly one character (except /).
Examples:
file?.txtmatchesfile1.txt,fileA.txt, but notfile10.txt(two chars) orfile.txt(zero char).???.pngmatches any.pngfile with a three-character name (like001.png,cat.png).
# Show PNG files with 3-character names
ls ???.png
# Match exactly one character between prefix and suffix
ls report-?.pdfCharacter classes: `[...]`
Square brackets [...] match one character from a set or range.
Basic forms:
[abc]— matchaorborc[0-9]— match any digit[a-z]— lowercase letters[A-Z]— uppercase letters[A-Za-z0-9]— any letter or digit
Examples:
# Files named file1.txt, file2.txt, file3.txt
ls file[123].txt
# Images numbered 0-9
ls img[0-9].png
# Files starting with any letter, then .txt
ls [A-Za-z].txt
A hyphen - inside [] means a range if placed between characters, like a-z. Put - at the start or end if you need a literal -, e.g. [-abc] or [abc-].
Negated classes: `[^...]`
[^...] matches any single character not in the set.
Examples:
[^0-9].txt—.txtfiles whose first character is not* a digit.file[^a-z].txt—file1.txt,file_.txt, but notfilea.txt.
# Everything that does NOT start with dot
ls [^.]*
# All .log files whose names do not start with 'a'
ls [^a]*.logMatching hidden files
On Linux, filenames starting with . are hidden. Wildcards like * and ? do not match them by default.
Examples:
ls *— matchesfile.txt,image.png, but not.bashrc.ls .*— matches.bashrc,.config,..,.etc. (be careful).
To include hidden files explicitly:
ls .*— only hidden files (plus.and..)ls .[^.]*— hidden files, excluding.and..rm .*.swp— delete hidden swap files with.swpextension
Some tools (like bash with certain options, or file managers) can change this behavior, but the default is: * ignores dotfiles.
Globbing and directories
Wildcards can be used in directory names too.
Examples:
# List all items in any directory that starts with "logs"
ls logs*/
# Copy all .png files from all user directories: /home/*/Pictures
cp /home/*/Pictures/*.png /backup/pictures/
# List all .conf files in any subdirectory of /etc whose name ends with 'd'
ls /etc/*d/*.confNotes:
dir/—matches directory names (and files),/restricts the final match to directories (only entries that can be followed by/)./— a file or directory exactly one level down.
Brace expansion vs globbing
Brace expansion looks similar to globs but is different. It creates strings from a pattern and does not depend on filesystem contents.
Examples:
# Brace expansion - produces literal names
echo file{1,2,3}.txt
# -> file1.txt file2.txt file3.txt
# Globbing - matches existing files
echo file*.txtKey points:
- Brace expansion (
{a,b,c}) happens before globbing. {a,b}does not mean “any of a or b” as a glob; it is simple text generation.
You can combine them:
# Copy both .jpg and .png files
cp *.{jpg,png} /backup/images/
Here, .{jpg,png} becomes .jpg .png, and then each is globbed.
Escaping wildcards to use them literally
Sometimes you want a literal * or ? in a command (e.g. matching text inside a file, not filenames).
You can prevent globbing by:
- Quoting the pattern:
'*.txt'"data?.csv"- Escaping special characters with backslash
\: \*,\?,\[,\]
Examples:
# Search for the literal string "*.log" inside files
grep "*.log" notes.txt
# Create a file literally named "data*.txt"
touch 'data*.txt'
# Show a pattern without expanding it
echo \*.txt
Inside single quotes, * and ? lose their special meaning completely.
Combining patterns
You can mix *, ?, and [...] to build precise matches.
Examples:
# Files that start with "log-", then 4 digits, then ".txt"
ls log-????.txt
# config-1.conf, config-2.conf, config-A.conf but not config-10.conf
ls config-[0-9A-Z].conf
# Files that start with 'backup-' and end in .tar.gz or .tgz
ls backup-*.tar.gz backup-*.tgz
# Photos from 2023 January – March, day 01-09
ls photo-2023-0[1-3]-0[1-9].jpgYou can also use multiple globs in a single command:
# Remove both .tmp and .bak files
rm *.tmp *.bakRecursive globs: `**` (bash extended globstar)
Some shells support a special pattern ** that matches directories recursively when enabled.
In bash, you must turn it on:
shopt -s globstarThen:
**— matches zero or more directories, recursively.**/*.txt— all.txtfiles in current directory and all subdirectories.src/**/*.c— all.cfiles anywhere undersrc/.
Examples:
# List all .py files under current directory tree
shopt -s globstar
ls **/*.py
# Copy all .conf files from /etc and all subdirectories
shopt -s globstar
cp /etc/**/*.conf /backup/etc-configs/
Without globstar, ** is treated like * (non-recursive).
When globs match nothing
What happens if a pattern matches no files depends on shell settings.
Common behaviors:
- bash (default): leaves the pattern as-is.
ls *.nope
# ls: cannot access '*.nope': No such file or directory- With
nullglobenabled, unmatched patterns expand to nothing:
shopt -s nullglob
echo *.nope
# (prints nothing)Be aware of this when writing scripts; patterns that match nothing can cause surprising results.
Safety tips (especially with `rm`)
Wildcards are powerful—and dangerous—when deleting.
Guidelines:
- Always test with
lsfirst:
# Check what will be removed
ls *.log
# Then, if it looks correct:
rm *.log- Avoid running destructive commands from the wrong directory. Use absolute or explicit paths:
rm /var/log/*.log- Be extra careful with
*afterrm: rm *– deletes everything (non-hidden) in current directory.rm -rf *– deletes everything recursively; a typo here can be catastrophic.- Consider using interactive mode while learning:
rm -i *.log
rm -i asks for confirmation for each file.
Practical examples
A few common real-world patterns:
# Delete all temporary files ending with ~
rm *~
# Archive log files with date in the name, e.g., app-2023-01-01.log
tar czf logs.tar.gz app-2023-*.log
# Move all PDFs and images to Documents
mv *.{pdf,PDF,jpg,jpeg,png} ~/Documents/
# List only directories (using trailing slash)
ls -d */
# Delete all files whose names start with a digit
rm [0-9]*
# List all ".conf" files in /etc and one level of subdirectories
ls /etc/*.conf /etc/*/*.confUnderstanding wildcards and globbing allows you to interact efficiently with large numbers of files using concise patterns, rather than typing each filename individually.