Bash 路径中的平铺不';t扩展到主目录

Bash 路径中的平铺不';t扩展到主目录,bash,syntax,tilde-expansion,Bash,Syntax,Tilde Expansion,假设我有一个名为Foo的文件夹,位于/home/user/中(我的/home/user也由~表示) 我想要一个变量 a=“~/Foo”然后执行 cd$a 我明白了 -bash:cd:~/Foo:没有这样的文件或目录 但是,如果我只做cd~/Foo它就可以了。关于如何使其工作的任何线索?您可以使用$HOME而不是tilde(tilde由shell扩展到$HOME的内容)。 例如: 您可以执行以下操作(在变量赋值期间不使用引号): 但是在这种情况下,变量$a将不存储~/Foo,而是存储扩展形式/ho

假设我有一个名为
Foo
的文件夹,位于
/home/user/
中(我的
/home/user
也由
~
表示)

我想要一个变量

a=“~/Foo”
然后执行

cd$a

我明白了
-bash:cd:~/Foo:没有这样的文件或目录


但是,如果我只做
cd~/Foo
它就可以了。关于如何使其工作的任何线索?

您可以使用
$HOME
而不是tilde(tilde由shell扩展到
$HOME
的内容)。 例如:

您可以执行以下操作(在变量赋值期间不使用引号):

但是在这种情况下,变量
$a
将不存储
~/Foo
,而是存储扩展形式
/home/user/Foo
。或者您可以使用
eval

a="~/Foo"
eval cd "$a"

如果使用双引号,~将作为该字符保留在$a中

cd$a将不会展开~,因为shell不会展开变量值

解决办法是:


eval“cd$a”

一个更健壮的解决方案是使用sed或更好的bash参数扩展:

somedir="~/Foo/test~/ing";
cd "${somedir/#\~/$HOME}"
或者如果您必须使用sed

cd $(echo "$somedir" | sed "s#^~#$HOME#")

虽然这个问题只是要求解决问题,但这是许多问题的重复,这些问题都在问为什么会发生这种情况,所以我认为值得给出一个解释。根据:

单词扩展顺序如下:

应从头到尾执行波浪线展开、参数展开、命令替换和算术展开


当shell对字符串
cd$a
求值时,它首先执行tilde扩展(这是一个不可操作的操作,因为
$a
不包含tilde),然后将
$a
扩展到字符串
~/Foo
,这是最后作为参数传递给
cd
的字符串,谢谢!评估cd起作用了。我确实想保持“~/Foo”的完整性,所以这个解决方案是有效的。起初我尝试了cd
eval$a
,但没有成功。这里也应该突出地标记禁止使用
eval
的常见警告。切勿对未经清理的数据运行
eval
,或以安全的方式自行构建数据。不幸的是,如果目录名包含空格,则此操作将无效<代码>a=“~/dir,带空格”;eval cd“$a”=>
-bash:cd:/Users/jack/dir:没有这样的文件或目录
:-(@duthen:您可以使用somwhat丑陋的变体
cd“$(eval echo“$a”)”
一种明智而正确的写入方式,即
a=~/dir\with\spaces
或等效的
a=~/“dir with spaces”
如果你的名字不是“约翰·F”,引用有什么好处,为什么是分号?感谢您提到tilde实际上扩展到$HOME,在我看来它更可读。@userunknown,如果您省略引号,您告诉shell做更多的事情,这些事情都有失败的案例。如果有人设置
IFS=/
读取斜杠分隔的输入,例如,
cd$dir
即使没有空格也会出现错误行为。展开字符串时不带引号会告诉shell拆分字符串并全局展开它们。为什么要编写代码来指示shell执行您不希望它执行的操作?不幸的是,如果您尝试引用其他人的主目录,这将不起作用。
somedir=“~jack/TMP”;cd${somedir/#\~/$HOME}
=>
-bash:cd:/Users/jackjack/TMP:没有这样的文件或目录
:-(这里的人可能感兴趣:。我强烈建议您不要在这个问题或其他地方使用任何指示您使用
eval
的答案;请参阅。
somedir="~/Foo/test~/ing";
cd "${somedir/#\~/$HOME}"
cd $(echo "$somedir" | sed "s#^~#$HOME#")