shell-conventionslisted
Install: claude install-skill AntheaLaffy/the-missing-semester-skills
# 命令行约定
主线:Shell 语言本身几乎不强制任何语法,程序之间的默契全靠约定——参数、流、环境变量、返回码。懂约定才能读懂别人写的脚本,也才能写出与其他程序良好协作的命令。
## 参数
- 参数是纯字符串,由程序决定怎么解析。`$1`–`$9` 逐个访问,`$@` 全部,`$#` 个数,`$0` 程序名。
- 选项以 `-` 或 `--` 开头:`-a` 单字母(可合并成 `ls -la`)、`--all` 长名称(通常等价);顺序无所谓;`--help`/`--verbose`/`--version` 先试。
- 选项解析是程序自己的事,Shell 并不替你解析——写 CLI 程序时用现成解析库(如 Python 的 argparse),别手写。
- `--` 终止选项解析:后面全是位置参数——文件名以 `-` 开头时必需(`touch -- -myfile`,删除时 `rm -- -myfile`)。
- 同一命令常接受多个同类参数(`mkdir src docs`),配合 glob 威力最大:`*` 匹配任意字符、`?` 恰好一个、`{a,b}` 花括号展开——Shell 在调用程序前就展开,`rm *.py` 传给 rm 的是文件列表而不是字符串 `*.py`;zsh 还支持 `**` 递归匹配(`rm **/*.py`)。
## 流
- stdin/stdout/stderr 三条流;管道只传 stdout,stderr 直接上终端——错误信息不污染管道数据。
- 管道是并行的:所有程序同时启动、流先接好,数据边产出边消费——不是「前一个跑完才跑下一个」。注意程序可能缓冲输出(Python 默认缓冲),慢速管道里「数字迟迟不出现」多半是缓冲,可用 `python -u` 关掉。
- `-` 作为文件名常表示 stdin(`echo hi | grep hi -` 与不加 `-` 等价)。
- 重定向:`>` 覆盖、`>>` 追加、`2>` 接 stderr、`&>` 两流同文件、`<` 读文件、`cmd > /dev/null 2>&1` 全丢弃。
- `fzf` 从 stdin 读行、交互筛选:`ls | fzf`、`cat ~/.bash_history | fzf`;配置 shell 集成后 Ctrl-R 的历史搜索也用它。
## 环境变量
- `foo=bar` 赋值、`$foo` 读取;`foo = bar` 会被解析成调用程序 foo 并传参 `['=', 'bar']`——等号两边不能有空格。
- 变量全是字符串;`'...'` 字面量不展开变量,`"..."` 会展开。
- 命令替换 `$(...)`:`files=$(ls)` 把 stdout 存进变量(保留换行,grep 等仍能按行处理)。
- 进程替换 `<( CMD )`:把命令输出变成临时文件路径,喂给只收文件参数的命令——`diff <(ls src) <(ls docs)`。
- 环境变量随子进程传递:`TZ=Asia/Tokyo date` 只对这一次生效;`export DEBUG=1` 之后所有子进程继承;`unset DEBUG` 删除。export 是把变量标记为「可继承」,标记之后再改值,子进程拿到的也是新值。按约定环境变量全大写(HOME、PATH、DEBUG),与本地变量区分。
## 返回码
- 0 = 成功,非 0 = 失败;`exit NUM` 主动返回,`$?` 取上一条的返回码。
- `&&`/`||` 按