在BASH脚本中,我正在尝试检测文件是否存在。文件名在变量中,但-e命令似乎无法检测到该文件。以下代码始终输出“〜/ misc / tasks / drupal_backup.sh不存在”
filename="~/misc/tasks/drupal_backup.sh"
if [ -e "$filename" ]; then
echo "$filename exists"
else
echo "$filename does not exist"
fi
另一方面,以下代码正确检测文件:
if [ -e ~/misc/tasks/drupal_backup.sh ]; then
echo "$filename exists"
else
echo "$filename does not exist"
fi
为什么会这样?当文件名在变量中时,如何让它检测文件?
答案 0 :(得分:7)
这是一个有趣的。将$HOME
替换为~
与删除分配中的引号一样。
如果您在该脚本的顶部放置set -x
,您会看到带引号的版本将文件名设置为~/...
,这是-e
的内容。如果删除引号,则将filename设置为展开的/home/somebody/...
。所以在第一种情况下,你会看到:
+ [ -e ~/... ]
它并不喜欢它。在第二种情况下,您会看到:
+ [ -e /home/somebody/... ]
并且 工作。
如果你没有变量,你会看到:
+ [ -e /home/somebody/... ]
并且,是的,它有效。
经过一番调查后,我发现它实际上是bash
执行扩展的顺序。从bash手册页:
扩展的顺序是:大括号扩展,波浪扩展,参数,变量和算术扩展以及命令替换(以从左到右的方式完成),单词拆分和路径名扩展。
这就是为什么它不起作用,变量在波浪号扩展之后被替换为。换句话说,在bash
想要展开~
时,没有一个。~/...
。只有在变量扩展后,单词才会变为if
,之后就不会有波浪扩展。
您可以做的一件事就是将您的if [[ -e $(eval echo $filename) ]]; then
声明更改为:
eval
这将两次评估$ filename参数。第一次(使用~
),在代字段扩展阶段将不会有$filename
,但在变量扩展阶段~/...
将更改为if
。
然后,在第二次评估(作为~
本身的一部分完成的评估)中,.profile
将在波浪扩展阶段进行。
我已经在我的{{1}}文件上对其进行了测试,它似乎有效,我建议您在特定情况下进行确认。