PATH 里的波浪号未必是你的 HOME
在 shell 命令中使用 `~`——尤其是在修改 `PATH` 时——的行为可能与许多人的预期大不相同,因为波浪号展开只在特定的未加引号位置发生,而且在 POSIX shell 与 Bash/Zsh 扩展之间也不一致。评论者分享了诸如把字面量 `~` 误插入 `PATH`,甚至误删 `$HOME` 之类的坑,并讨论用户本地目录是否应排在系统路径之前,同时将 Bash 众多“陷阱”与 fish、nushell、zsh 等替代 shell 作对比。这场讨论凸显了细微的引号与展开规则,再加上不一致的工具和文档,使得稳健的 shell 使用与脚本编写比表面上更困难。
波浪号展开与 PATH 行为
- 波浪号只会在特定位置展开(未加引号的“单词”开头;在某些 shell 中,赋值中未加引号的冒号后面也会展开)。
- 给
~加引号会阻止展开,并可能让 PATH 里保留字面量~,这就是原始问题。 - 某些 shell(zsh、fish)提供了更方便或基于数组的方式把
~/.local/bin加到 PATH 中,能正确处理展开。 - 几位评论者更喜欢在脚本里用
$HOME而不是~,以避免意外。
引号规则与常见 shell 陷阱
- 误解何时该加引号是 bug 的主要来源:人们既会过度加引号,也会加得不够。
- 给出的建议:
- 在参数中总是给变量展开加引号(
"$var"),以避免单词拆分和通配展开。 - 只在包含特殊字符的字面量字符串上使用单引号。
- 在参数中总是给变量展开加引号(
- 变量展开和波浪号展开的行为不同;把它们当成一样会导致错误。
PATH 的顺序与安全性
- 对于是否应把
~/.local/bin这类用户目录放在前面还是后面,存在争论。- 一派主张追加到后面,让系统二进制优先,以降低恶意覆盖的风险。
- 另一派主张放在前面,这样用户可以有意覆盖过时的系统工具。
- 普遍共识是:如果攻击者能写入你的 PATH 目录,那你已经遭遇严重入侵了。
POSIX 与 shell 特有行为
- 文章中的某些行为依赖 bash/zsh 扩展,对
/bin/sh(通常是dash或ash)并不具备可移植性。 - 评论中引用了 POSIX 的波浪号展开规则;起初有些混淆,后来澄清在赋值中未加引号的
:后面是允许展开的。 - 多次提醒要区分“bashism”和严格符合 POSIX 的构造。
替代 shell 与语言选择
- 很多人批评 bash 是一种“糟糕”或脆弱的脚本语言,边界情况太多。
- 提到的替代方案包括:fish、zsh、nushell、murex、PowerShell、Perl、Ruby 等。
- 反方观点是:bash/sh 之所以占主导,是因为它们几乎到处都预装,尤其是在远程系统上。
文件名、字符与健壮性
- 有人认为如果路径只允许受限的 ASCII 集合,生活会更简单,这样能避免编码和解析问题。
- 也有人强烈支持非拉丁脚本和任意 Unicode,尽管这会给工具带来麻烦。
- 文件名中包含空格或以
-开头被指出是 bug 和安全隐患的常见来源。
环境、HOME 与调试
- 有人指出
$HOME与系统数据库中的账户 home 目录并不完全相同;二者可能不一致,并让~的解析变得混乱。 - 为测试而修改 HOME 可能会与以不同方式解析 home 目录的工具发生冲突。
- 大型组织通常拥有层层嵌套的 shell 启动文件,很难追踪变量到底在哪里被设置;因此有人推荐使用 shell 启动追踪工具。
真实事故与经验教训
- 有多个轶事:创建了字面量的
~目录、误执行rm -r ~、以及 AI 工具创建~目录。 - 总结出的教训包括:尽量避免使用
rm -r,使用更明确的路径(./~),并谨慎对待 shell 特性。