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

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

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

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。

答案1

简短回答:参见Bash常见问题解答 #050(“我试图将命令放入变量中,但复杂的情况总是失败!”)。

长答案:当 bash 解析命令时,它会在替换变量之前解析引号;它永远不会返回并重新解析变量值中的引号,因此它们最终不会做任何有用的事情。使用 echo 检查命令完全是误导,因为它会显示命令它已被解析;如果您想查看实际正在执行的内容,可以使用set -xshell 打印正在执行的命令,或使用printf "%q " $dir; echo它而不是简单的 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

答案2

当 bash 扩展 时$dir,它只对其进行分词和通配。分词产生三个单词: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你的.bashrc并设置

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

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

答案3

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

而不是

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对于别名或函数来说,And可能是一个不合适的名称,因为已经有一个同名的命令(它基本上是 的一个版本ls,至少如果你有 GNU coreutils 的话)。

答案4

尝试

bash$ echo  'This   is   "a     long"  line' > mylist
bash$ echo @mylist
@mylist
bash$ cmd
c:\> c:\cygwin\bin\echo @mylist
This is a     long line

更具体地说:

https://stackoverflow.com/questions/4334467/cygwin-using-a-path-variable-containing-a-windows-path-with-a-space-in-it

相关内容