Wildcards

What if you want to delete all .log files? Or copy all files starting with test_?

You could list them all manually. Or you could use wildcards.

The * Wildcard

* matches any number of characters (including zero):

Terminal
$ls *.txt
notes.txt readme.txt todo.txt
$ls report*
report.pdf report_final.pdf report_v2.pdf
$ls *2024*
budget_2024.xlsx log_2024_01.txt report_2024.pdf

Common Patterns

hljs bash
*.txt           # All .txt files
test_*          # Files starting with "test_"
*.tar.gz        # All .tar.gz archives
*config*        # Files containing "config"

The ? Wildcard

? matches exactly one character:

Terminal
$ls file?.txt
file1.txt file2.txt file3.txt
$ls ???.txt
abc.txt xyz.txt

* vs ?

* = zero or more characters ? = exactly one character

file* matches file, file1, file123 file? matches only file1, fileA (exactly 5 characters)

Character Classes [ ]

Match specific characters:

Terminal
$ls file[123].txt
file1.txt file2.txt file3.txt
$ls file[0-9].txt
file0.txt file1.txt ... file9.txt
$ls [A-Z]*.txt
Report.txt Summary.txt

Ranges

hljs bash
[0-9]       # Any digit
[a-z]       # Any lowercase letter
[A-Z]       # Any uppercase letter
[a-zA-Z]    # Any letter
[a-zA-Z0-9] # Any alphanumeric

Negation

hljs bash
[!0-9]      # NOT a digit
[^abc]      # NOT a, b, or c

Brace Expansion

This is different from wildcards - it's expansion by the shell:

Terminal
$echo file{1,2,3}.txt
file1.txt file2.txt file3.txt
$echo {a,b,c}_{1,2}
a_1 a_2 b_1 b_2 c_1 c_2
$echo file{1..5}.txt
file1.txt file2.txt file3.txt file4.txt file5.txt

Wildcards vs Braces

Wildcards match existing files. Braces generate strings (files don't need to exist).

hljs bash
ls *.txt          # Lists existing .txt files
touch file{1..5}  # Creates file1, file2, file3, file4, file5

Practical Examples

Delete All Logs

Terminal
$ls *.log
access.log error.log debug.log
$rm *.log

Copy All Images

Terminal
$cp *.{jpg,png,gif} images/

Backup Config Files

Terminal
$cp /etc/*.conf /backup/

Move Old Files

Terminal
$mv *_2023_* archive/

List Specific Extensions

Terminal
$ls *.{js,ts,tsx}
app.js utils.ts Button.tsx

Escaping Wildcards

What if you want a literal * or ??

Terminal
$ls 'file*.txt'
(looks for file literally named 'file*.txt')
$ls file\*.txt
(same thing, using backslash escape)

Quotes or backslash prevent expansion.

Hidden Files and *

By default, * doesn't match hidden files:

Terminal
$ls *
file1 file2 (no hidden files)
$ls .*
.bashrc .config (only hidden files)
$ls * .*
(both visible and hidden)
Knowledge Check

What does `ls file[0-9][0-9].txt` match?

Key Takeaways

  • * matches any number of characters
  • ? matches exactly one character
  • [abc] matches any one character in the set
  • [0-9] matches character ranges
  • {a,b,c} expands to multiple strings (not a wildcard)
  • * doesn't match hidden files by default
  • Quote or escape wildcards for literal characters

Next: the powerful find command for searching the filesystem.