Bash脚本 - 不检测变量中的文件名

时间:2010-06-28 02:41:31

标签: linux bash shell filenames

在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

为什么会这样?当文件名在变量中时,如何让它检测文件?

1 个答案:

答案 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}}文件上对其进行了测试,它似乎有效,我建议您在特定情况下进行确认。