Wildcards & Globbing — Match Files Without Typing Every Name
Master *, ?, [...], and {} to select files by pattern. Wildcards multiply your power — one command works on dozens or thousands of files at once.
Wildcards (also called globbing) let you describe a pattern instead of a specific filename. The shell expands the pattern to match all existing files before running the command — so rm *.log removes every .log file without you naming each one.
Globing is a shell feature, not a command feature — it works with ls, cp, mv, rm, cat, grep, or any command that takes file arguments.
Wildcard Characters
Glob Patterns
| Pattern | Matches | Example |
|---|---|---|
* | Any number of any characters (including zero) | *.txt → all .txt files |
? | Exactly one any character | file?.txt → file1.txt, fileA.txt |
[abc] | Any one character from the set | [abc]*.txt → starts with a, b, or c |
[a-z] | Any one character in the range | file[0-9].txt → file0 through file9 |
[!abc] or [^abc] | Any character NOT in the set | [!0-9]* → doesn't start with digit |
{a,b,c} | Brace expansion — generates strings (not a glob!) | {txt,md} → literally txt and md |
* — Match Any Characters
ls *.txt # All files ending in .txt
ls data_* # All files starting with data_
ls *report* # All files containing "report"
ls * # All files (everything)
rm *.log # Remove all .log files
cp *.{jpg,png} ~/Pictures/ # Copy all jpg and png to Pictures
mv /var/log/nginx/*.log /backup/ # Move all nginx logs to backup? — Exactly One Character
ls file?.txt # file1.txt, fileA.txt — NOT file10.txt (two chars)
ls ???.txt # Any 3-letter name with .txt extension
ls log?.conf # logA.conf, log1.conf, etc.
rm backup?.tar # backup1.tar through backup9.tar, backupA.tar...
# Difference between * and ?
ls file*.txt # Matches file.txt, file1.txt, file10.txt, filename.txt
ls file?.txt # Matches ONLY file1.txt, fileA.txt (exactly one char)[...] — Character Sets and Ranges
ls file[123].txt # file1.txt, file2.txt, file3.txt ONLY
ls file[a-z].txt # filea.txt through filez.txt
ls [A-Z]*.txt # Files starting with uppercase letter
ls file[0-9][0-9].txt # file00.txt through file99.txt
# Negated character sets
ls [!0-9]* # Files NOT starting with a digit
ls [^aeiou]* # Files not starting with a vowel{} — Brace Expansion
Brace expansion is not a glob — it doesn't match existing files. Instead it generates strings, whether or not those files exist. This makes it useful for creating files, renaming patterns, and building command arguments.
# Generate multiple filenames
touch file.{txt,md,json} # Creates file.txt, file.md, file.json
mkdir {frontend,backend}/{src,tests} # Creates 4 directories
cp config.yaml{,.bak} # Shorthand: copies config.yaml to config.yaml.bak
# Number ranges
touch file{1..5}.txt # file1.txt through file5.txt
echo {A..Z} # A B C D ... Z
echo {01..10} # 01 02 03 ... 10 (zero-padded)
# Nested braces
mkdir -p project/{src/{components,utils},tests/{unit,e2e}}Combining Patterns
ls *.{jpg,png,gif} # All image files
cp data_????_*.csv /backup/ # data_ + exactly 4 chars + _ + anything .csv
ls [A-Z]*.[ch] # Uppercase-start C source or header files
find . -name "[!.]*" # Files not starting with dot (non-hidden)
# Real-world: process all log files from Jan-Mar 2024
cat /var/log/nginx/access.log.2024-0[1-3]* # Jan=01, Feb=02, Mar=03You want to match `file1.txt`, `file2.txt`, and `file3.txt` but NOT `file10.txt` or `file.txt`. Which glob is correct?
Create test files and practice globbing:
touch file{1..5}.txt fileA.txt fileB.txt data_report.csv notes.md
- List only the numbered files:
file1.txtthroughfile5.txt - List files starting with
fileand ending with .txt (including fileA, fileB) - List only file1, file2, file3 (not fileA, fileB, file4, file5)
- List all files that are NOT .txt files
- Create a backup of every .txt file in one command using brace expansion