通配符与花括号扩展是什么
通配符不是命令的功能,而是 shell 在启动命令之前完成的文件名展开(globbing):shell 先把 *.log 展开成一串真实文件名,再把它们当作参数交给命令。花括号扩展 {a,b} 更进一步,它不检查文件是否存在,纯粹把一个词展开成多个词。理解「谁先展开」是写好命令的关键——很多「命令参数没生效」的问题,本质是 shell 提前替它做了决定。
基本信息
| 适用范围 | bash、zsh 等 shell;POSIX sh(如 dash)支持通配符但不支持花括号扩展 |
|---|---|
| 常用符号 | * 任意长度 ? 单个字符 [abc]/[a-z] 字符集合 [!abc] 取反 {a,b} 花括号 |
| 展开时机 | 命令执行之前,由 shell 完成;用 echo 可以预览展开结果 |
| 阻止展开 | 单引号或双引号包住模式,或用反斜杠转义单个字符 |
典型使用场景
- 批量操作文件:按后缀、前缀或编号范围批量改名、压缩、复制
- 生成多份配置:一次展开成多个目标,省掉重复命令
- 数字序列展开:{1..5}、{01..10} 这类按序编号在脚本里非常实用
- 预览危险操作:执行删除或覆盖前,先用 echo 看模式会展开成什么
- 脚本健壮性:处理「一个都没匹配上」的边界,避免把模式本身当成文件名传给命令
常用示例
常用示例
ls *.log # 匹配任意后缀
rm -i file?.txt # 单字符占位,-i 逐个确认
ls [abc]*.conf # 以 a/b/c 开头
ls [!0-9]*.conf # 首字符不是数字
mkdir -p data/{raw,clean,tmp} # 一次建三个目录
cp app.conf{,.bak} # 展开为两个参数,等价于先备后写
echo backup-{01..05}.sql # 序列展开,带前导零
echo *.xyz # 无匹配时原样输出,用于自检匹配符号对照
| 写法 | 匹配范围 | 注意 |
|---|---|---|
| * | 任意长度字符,不跨路径分隔符 | 不匹配以点开头的隐藏文件 |
| ? | 恰好一个字符 | 文件名的字符数要对得上 |
| [abc] / [a-z] | 集合中的一个字符 | 区间按本地化排序,跨语言场景谨慎 |
| [!abc] | 不在集合中的字符 | bash 里也接受 [^abc] |
| {a,b,c} | 展开成多个独立词 | 不检查文件是否存在,POSIX sh 不支持 |
| {1..5} / {a..e} | 序列展开 | 支持前导零写法,如 {01..10} |
无匹配时的默认行为是把模式原样传给命令,于是 ls *.xyz 会报「找不到 *.xyz」。脚本里可以开 shopt -s nullglob 让无匹配展开为空,或用 failglob 让它直接报错退出,两种取舍取决于你希望静默还是显式失败。
破坏性命令前先预览:执行 rm 或覆盖操作用先 echo 同样的模式,确认展开结果与预期一致。rm -f 配合无匹配的模式会静默什么也不做,看起来像执行成功,这种假成功更难发现。