为什么在shell脚本中路径中的波浪号不被展开?

21
我尝试让Android Studio启动器(studio.sh)使用我手动安装的Java(而不是系统默认的Java)。因为我已经在我的.bashrc文件中声明了PATH和JAVA_HOME,所以我只需在shell脚本中源化该文件:
. /home/foobar/.bashrc
但由于某种原因,$JAVA_HOME/bin/java仍然没有被脚本识别为可执行文件。
我添加了一些日志记录并发现JAVA_HOME被展开为~/install/java......,即波浪号运算符没有展开成主目录。
我进行了一些搜索,但找不到它未被展开的原因。是波浪号一个Bash特定的功能(脚本使用#!/bin/sh,Linux Mint使用dash而不是bash)?在某些情况下,波浪号不起作用吗?
我在我的.bashrc声明中用$HOME替换了~,然后它就起作用了,所以HOME在运行时是已知的。
1个回答

26
Bash手册中指出,在参数替换时进行花括号扩展,但不递归扩展:

扩展的顺序是:花括号扩展;家目录(~)扩展、参数和变量扩展、算术扩展和命令替换(从左至右);单词分割;文件名扩展。

这意味着在Bash变量中存储未扩展的家目录(~)、参数引用或命令替换将不会自动解析。您的JAVA_HOME变量包含一个实际的家目录(~),因此Bash不会自动展开它。
很可能您的修复工作是因为引号中不适用家目录(~)扩展。
$ echo "~"
~
$ echo ~
/home/jeffbowman

……但是像$HOME这样的参数扩展在引号内确实会发生。用$HOME替换它会在分配JAVA_HOME期间扩展为您的主目录。

FOO=~/bar        # stores /home/jeffbowman/bar
FOO="~/bar"      # stores ~/bar
FOO=$HOME/bar    # stores /home/jeffbowman/bar
FOO="$HOME/bar"  # stores /home/jeffbowman/bar

虽然更好的选择是确保您的作业正确,但如果您想手动扩展它,这些SO问题有一些不错的选项:


这个答案可能更好,可以指向这里,但我并没有仔细看你链接的那个。 - Etan Reisner
@EtanReisner 谢谢。有一些长期存在的“扩展我的存储波浪号”的问题可能需要去重。那是个好问题,我会编辑进去的。(我宁愿链接到问题而不是答案,因为了解每个答案的优缺点是有用的。) - Jeff Bowman
是的,我已经打开了几个类似的标签一段时间了,等着我决定如何很好地去重它们。我差点发了一个元问题,询问是否可能让管理员将一些更好的答案迁移到一个新的经典提问中或者其他什么的。 - Etan Reisner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接