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

tho*_*ate 5 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
Run Code Online (Sandbox Code Playgroud)

另一方面,以下代码正确检测文件:

if [ -e ~/misc/tasks/drupal_backup.sh ]; then
  echo "$filename exists"
else 
  echo "$filename does not exist"
fi
Run Code Online (Sandbox Code Playgroud)

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

pax*_*blo 7

这是一个有趣的.代$HOME~作品并除去转让的报价.

如果你把一个set -x放在该脚本的顶部,你会看到带引号的版本将文件名设置为~/...给出的内容-e.如果删除引号,则将filename设置为展开/home/somebody/....所以在第一种情况下,您会看到:

+ [ -e ~/... ]
Run Code Online (Sandbox Code Playgroud)

并且它不喜欢它.在第二种情况下,您会看到:

+ [ -e /home/somebody/... ]
Run Code Online (Sandbox Code Playgroud)

确实有效.

如果你在没有变量的情况下这样做,你会看到:

+ [ -e /home/somebody/... ]
Run Code Online (Sandbox Code Playgroud)

而且,是的,它有效.


经过一番调查后,我发现它实际上是bash执行扩展的顺序.从bash手册页:

扩展的顺序是:括号扩展,波浪扩展,参数,变量和算术扩展和命令替换(以从左到右的方式完成),单词拆分和路径名扩展.

这就是为什么它不起作用,变量在波浪扩展后被替换.换句话说,在bash想要扩展的点上~,没有一个.只有在变量扩展之后,单词~/...才会变为,之后就不会出现波浪扩展.

可以做的一件事是将你的if陈述改为:

if [[ -e $(eval echo $filename) ]]; then
Run Code Online (Sandbox Code Playgroud)

这将两次评估$ filename参数.第一次(with eval),~在波浪扩展阶段期间将不存在,但在变量扩展阶段期间$filename将更改为~/....

然后,在第二次评估(作为if自身的一部分完成的评估)中,~在波浪扩展阶段期间将存在.

我已经在我的.profile文件上测试了它,它似乎工作,我建议你在你的特定情况下确认.