一条命令的旅程
从回车到执行,Shell 按固定顺序处理一行命令。搞清顺序,引号和空格的怪行为都能解释。
展开顺序
| 步骤 | 例子 | 结果 |
|---|---|---|
| 花括号展开 | {a,b}.txt | a.txt b.txt |
| 波浪号展开 | ~/bin | /home/me/bin |
| 参数替换 | $HOME | /home/me |
| 命令替换 | $(date) | 2026-11-06 |
| 切词 | $files | 按 IFS 拆成多个词 |
| 文件名展开 | *.py | a.py b.py |
引号
| 写法 | 变量展开 | 切词保护 | 典型用途 |
|---|---|---|---|
'...' | 否 | 是 | 字面量、正则 |
"..." | 是 | 是 | 带空格的变量 |
$'...' | 否 | 是 | \n、\t 转义 |
\x | 否 | 单字符 | 转义特殊字符 |
bash
files="a b"
rm $files # 两个参数
rm "$files" # 一个参数变量与替换
$HOME与${HOME}等价,${HOME}dir用来划边界export把变量放进环境,子进程才能继承$(...)去掉末尾换行,保留中间换行- 反引号是旧写法,不能嵌套
glob
| 模式 | 匹配 |
|---|---|
* | 任意长度字符 |
? | 单个字符 |
[abc] | 字符集合 |
** | 递归目录,需 globstar |
- 默认不匹配隐藏文件,
.和..不参与 - 无匹配时 bash 保留原样,
nullglob变空,failglob报错 - 花括号展开在 glob 之前,不要求文件存在
查找与执行
- 按
:拆开$PATH,从左到右找第一个同名可执行文件 type -a显示所有候选,command -v是 POSIX 写法hash -r清掉路径缓存- 外部命令走
fork+exec+wait cd、export、umask是内建,因为子进程改不了父进程
bash
type -a python
hash -r
set -x # 打印展开后的命令set -x 是验证展开顺序最快的方式,比在脑子里模拟可靠。