Bash波浪号在某些参数中没有扩展,例如--home_dir=~

Bash tilde not expanding in certain arguments, such as --home_dir=~

Bash 没有扩展参数 --home_dir=~ 中的 ~ 字符。例如:

$ echo --home_dir=~
--home_dir=~

Bash 会展开 ~ 当我省略连字符时:

$ echo home_dir=~
home_dir=/home/reedwm

为什么 Bash 有这种行为?这很烦人,因为当我将该路径指定为命令的参数时,带有 ~ 的路径不会展开。

嗯,那是因为在 echo --home_dir=~ 中,'~' 没有 开始这个词 并且 echo 的输出不被认为是一个变量赋值。具体来说,man bash "Tilde Expansion" 提供扩展 if

  • 如果单词以未加引号的波浪字符开头 (~);或
  • 检查紧跟在 : 或第一个 =.
  • 之后的未引号波浪号前缀的变量赋值

你的情况也不符合。

bash 有点错误地将 home_dir=~ 视为赋值。因此,~ 符合扩展条件:

Each variable assignment is checked for unquoted tilde-prefixes immediately following a : or the first =. In these cases, tilde expansion is also performed.

由于 --home_dir 不是有效的标识符,因此该字符串 被误认为是赋值。

可以说,您发现了 bash 中的错误。 (我说有争议,因为如果你使用 set -k,那么 home_dir=~ 一个赋值,即使它在命令名称之后,而不是之前。)


但是,如果有疑问,请引用一个字符串,无论它是否受到任何类型的 shell 处理,都应按字面意思处理。

echo '--home_dir=~'

更新:根据维护者的说法,这是有意为 make 等命令允许类似赋值的参数,以利用波浪号扩展。 (还有像 export 这样的命令,出于某种原因我认为它们很特别,因为它们是内置的,但波浪号扩展必须在实际命令已知之前发生。)

正如 chepner 在他们的回答中所说,根据文档,即使在 echo home_dir=~ 中也不应该扩展它。但出于某种原因,它确实在任何看起来像赋值的单词中扩展了它,并且至少早在 3.2 中就已经这样做了。

大多数其他 shell 也不会扩展波浪号,除非波浪号确实位于单词的开头,因此依赖它工作可能不是一个好主意。

如果您希望它展开,请使用 "$HOME",如果您想要字面波浪号,请使用 "~"。例如

$ echo "~" --foo="$HOME"
~ --foo=/home/itvirta

(越复杂的情况越难手动完成,但大多数情况下是 运行 用户自己的主目录。)