Bash 引用嵌套和大括号

Bash quote nesting and curly braces

根据 Change gnome-terminal title to reflect the current directory? 我尝试使用:

PROMPT_COMMAND='echo -ne "3]0;$(basename ${PWD})[=11=]7"'

...在我的~/.bashrc标题栏中gnome-terminal表示当前目录的名称。

大部分情况下它工作正常;但是如果我尝试从以下目录打开 gnome-terminal

/run/user/1000/gvfs/mtp:host=%5Busb%3A001%2C008%5D/Internal shared storage/DCIM/Camera

...然后它失败了:

basename: extra operand ‘storage/DCIM/Camera’
Try 'basename --help' for more information.

...每次提示即将显示在终端中。

显然问题出在目录名中的空格(即使 ${PWD} 中的花括号原则上应该避免引号)。所以,我尝试用引号转义,结果证明这不是微不足道的(显然只是单引号转义 \"${PWD}\" 不起作用) - 我能得到的最好的是:

PROMPT_COMMAND='echo -ne "3]0;$(basename \\"${PWD}\\")[=14=]7"'

... 可以正常工作 - 但它会在 gnome-terminal 标题中打印一个额外的反斜杠;例如,在这种情况下,标题是:Camera\.

PROMPT_COMMAND 的正确构造是什么,以便它正确处理带空格的目录,并且只打印没有附加反斜杠的目录(例如 Camera)?

为什么要转义双引号?

PROMPT_COMMAND='echo -ne "3]0;$(basename "${PWD}")[=10=]7"'

是正确的。我们可以遍历嵌套级别:

  • 顶层单引号。在单引号内,您不需要转义双引号。您需要通过 '\''“转义”单引号(实际上,这是字符串连接,但这与此处无关)。

  • 二层双引号。在双引号内,如果您尝试编写文字 ",则需要 \"。然而,你还有第三层:

  • $() / 命令替换。该层在执行时不会在其周围看到双引号(单引号将是另一回事 - 您需要 '\'')。 Bash 将正确解析类似 echo "$(echo "my variable is $foo")".

    的内容

此外,${PWD} 中的花括号与引号无关。 ${PWD}$PWD从任何角度看都没有区别。只有当您的变量与其他“单词”字符对接时,花括号才会起作用:

echo PWD_$PWD_USER_$USER // expands variables "USER" and "PWD_USER_"
echo PWD_${PWD}_USER_$USER // expands variables "USER" and "PWD"