通配符用于匹配文件名,是 Shell 最常用的功能之一。与正则表达式不同,通配符由 Shell 解释,用于文件名扩展。Bash 还提供了花括号扩展、波浪号扩展等高级功能。
* 匹配 0 个或多个任意字符:
ls *.txt
rm *.log
cp *.jpg /backup/
? 匹配恰好一个任意字符:
ls file?.txt
ls ???.txt
匹配 file1.txt、file2.txt,不匹配 file10.txt。
[] 匹配方括号中的任意一个字符:
ls file[123].txt
ls file[1-3].txt
ls [abc]*
ls [!0-9]* # 排除数字开头
[!...] 或 [^...] 表示排除。
ls [[:alpha:]]*
ls [[:digit:]]*
ls [[:upper:]]*
花括号扩展生成多个字符串,不依赖文件是否存在。
echo {a,b,c}
echo file{1,2,3}.txt
mkdir dir{A,B,C}
输出:
a b c
file1.txt file2.txt file3.txt
echo {1..10}
echo {a..z}
echo {A..Z}
mkdir dir{1..10}
echo {0..10..2}
echo {a..z..3}
输出:
0 2 4 6 8 10
a d g j m p s v y
echo {a,b}{1,2,3}
echo /usr/{local/,}bin
输出:
a1 a2 a3 b1 b2 b3
/usr/local/bin /usr/bin
mkdir -p project/{src,doc,test}
cp file.{txt,bak}
mv style.{css,scss} backup/
for i in {1..10}; do echo $i; done
echo ~
echo ~/Documents
echo ~root
~ 是当前用户的家目录,~user 是指定用户的家目录。
echo ~+
echo ~-
~+ 是当前工作目录,~- 是上一个工作目录。
Shell 按以下顺序处理扩展:
echo ~/{a,b}*.txt
先扩展 ~,再扩展 {a,b},最后匹配 *.txt。
单引号内的所有字符原样保留:
echo '*.txt'
echo '{a,b,c}'
echo '$HOME'
反斜杠转义单个字符:
echo \*.txt
echo \$HOME
set -f 禁用文件名扩展:
set -f
echo *
set +f
Bash 支持 ksh 风格的扩展通配符,需要启用 extglob:
shopt -s extglob
| 模式 | 含义 |
|---|---|
?(pattern) | 匹配 0 次或 1 次 |
*(pattern) | 匹配 0 次或多次 |
+(pattern) | 匹配 1 次或多次 |
@(pattern) | 匹配恰好 1 次 |
!(pattern) | 匹配不包含 pattern |
ls *.?(txt|md)
ls *.+(jpg|png)
ls !(backup)
rm !(important).txt
shopt -s nocaseglob
ls *.TXT
启用后 *.txt 也能匹配 .TXT。
默认 * 不匹配以 . 开头的隐藏文件:
ls *
ls .*
ls * .*
.* 匹配隐藏文件,但也会匹配 . 和 ..。
更安全的方式:
ls .[!.]*
ls .[!.]* .??*
for f in *.txt; do
mv "$f" "${f%.txt}.md"
done
mkdir -p project/{src/{main,test},doc,config}
cp file.txt{,.bak}
for f in image{001..100}.jpg; do
convert "$f" "${f%.jpg}_thumb.jpg"
done
* 匹配任意字符,? 匹配单个字符,[] 字符集合{a,b} 和 {1..10}~ 扩展为用户目录shopt -s extglob 启用扩展通配符