当目录名称包含空格时,使用bash变量进入目录不起作用


11

假设我想将以下命令存储在变量中

cd "/cygdrive/c/Program Files/"

所以我这样做

dir="cd \"/cygdrive/c/Program Files/\""

那应该存储命令以导航到Program Files目录,所以当我键入$ dir时,它将带我到该目录。要检查报价是否已正确转义,我输入

echo $dir

这给了我

cd "/cygdrive/c/Program Files/"

因此,一切都应该正常工作。但是当我打字时

$dir

我懂了

bash: cd: "/cygdrive/c/Program: No such file or directory

我究竟做错了什么?我正在使用Cygwin,但我认为此问题通常适用于bash。


尝试删除目录名称周围的引号,并使用反斜杠转义空格。
Mike Fitzpatrick

Answers:


8

简短的答案:请参阅BashFAQ#050(“我试图将命令放入变量中,但是复杂的情况总是会失败!”)。

长答案:当bash解析命令时,它将解析引号,然后替换变量。它永远不会返回并重新解析变量值中的引号,因此它们最终无济于事。使用echo检查命令是完全误导的,因为它在解析命令会显示命令。如果您想查看实际执行的内容,请在执行时使用set -xshell打印命令,或者使用printf "%q " $dir; echo而不是普通回显。

如果要存储复杂的命令(例如,在“单词”中带有空格或其他特殊字符的命令),则需要将其放入数组中,而不是简单的文本变量,然后使用成语“''$ { array [@]}“,如下所示:

dir=(cd "/cygdrive/c/Program Files/")
"${dir[@]}"

现在,如果目的是制作易于键入的速记,显然这不是可行的方法。请改用Shell别名或函数:

alias dir='cd "/cygdrive/c/Program Files/"'
dir

要么

dir() { cd "/cygdrive/c/Program Files/"; }
dir

7

当bash扩展时$dir,它仅对其进行单词拆分和globing。分词产生三个词:cd"/cygdrive/c/ProgramFiles/"。然后要执行的命令cd带有两个参数。cd仅查看其第一个参数,"/cygdrive/c/Program它不是现有目录。

如果要对变量的内容执行完整的shell评估,请使用eval

eval "$dir"

请注意,您需要用双引号将引起来$dir,否则将首先执行单词拆分,然后eval将其参数与空格连接起来。这将在这里正常工作,但通常会变糟(例如,如果文件名中有两个连续的空格)。

但是,字符串不是存储要执行的Shell命令的正确方法。除非您有特殊要求,否则应改用函数:

dir () {
  cd "/cygdrive/c/Program Files/"
}

如果您真的有兴趣输入$dir以切换到特定目录,并且这不仅仅是一个简单的示例,因为bash 4放在shopt -s autocd您的.bashrcand set

dir="/cygdrive/c/Program Files/"

之后,您可以输入just "/cygdrive/c/Program Files/""$dir"在shell提示符下切换到该目录。您仍然需要双引号$dir;如果您不喜欢,请使用zsh而不是bash。


6

将命令存储在变量中通常不是一个好主意。这就是功能和别名的用途。

而不是

dir="cd \"/cygdrive/c/Program Files/\""

尝试以下方法之一:

dir="/cygdrive/c/Program Files"
...
cd "$dir"

要么

dir() { cd "/cygdrive/c/Program Files"; }
dir

要么

alias dir='cd "/tmp/Program Files"'
...
dir

第一种形式将目录名称存储在变量中,这意味着要多键入一些内容,但是当您执行正在执行的命令时,这种形式会更清楚cd。第二个是最接近您要完成的任务。(我在bash中使用的别名不多;实际上我不确定它们相对于功能有什么优势。)

编辑:

而且dir可能是一个别名或功能的恶名,因为有这个名字的存在的命令(这是基本的版本ls,至少如果你有GNU的coreutils)。


支持Storing commands in variables is generally not a good idea. That's what functions and aliases are for.
Rob

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.