使shell脚本对于它们被调用的位置健壮

编写一个shell脚本的最好方法是访问与之相关的文件,这样我就可以从中调用它。 “简单”意味着最简单/推荐的方式,将跨越不同的系统/炮弹工作。

说我有一个文件夹~/MyProject子文件夹scripts/files/ 。 在scripts/ ,我有一个shell脚本foo.sh ,它想要访问files/中的files/

 if [ -f "../files/somefile.ext" ]; then echo "File found" else echo "File not found" fi 

它会正常工作如果我做cd ~/MyProject/scripts && ./foo.sh ,但它将失败, cd ~/MyProject && scripts/foo.sh

你通常可以这样做:

 mydir="$(dirname $0)" 

获取正在运行的脚本的目录。

然后用它来找到你的文件。

使所有路径绝对。 尽可能使用环境变量,例如$ HOME。 您遇到了UNIX脚本的弱点。

使用.profile或.bash_profile,您的开发人员可以设置一堆ENV变量。 那么你的脚本就可以利用这些变量。

在我工作的地方之一,你可以运行一个脚本,它会提示你想要看哪个版本,并设置ENVs,这样开发人员的交互是非常无缝的。

不知道这对你来说是否容易,但这可能会给你一个解决方案:

Shell脚本加载程序

 if [ -f "../files/somefile.ext"] then echo "file was found" else echo "file was not found" fi 

第二:

 if [ ! -f /tmp/foo.txt ]; then echo "File not found!" fi 

不幸的是,似乎没有一个真正的通用解决方案。 我个人的建议(和实践)是只写shell提供一致的访问这个 – 最近ksh93${.sh.file}bash$BASH_SOURCE等(我不知道zsh解决方案,但我确定有一个。)

除此之外,最好的解决办法是以某种方式避免这个问题。 例如,对于git仓库中脚本的示例,您可能需要从其目录中调用该脚本。在通过检查[[ -e myscript ]]进行验证之后,您可以预期相关链接将作为预期。 (是的,为了完全健壮,您需要将脚本的基本名称硬编码到测试中,出于同样的原因,这个问题首先存在 – 它在所有可能的情况下都可用于shell。)

考虑到$0应该包含执行脚本的路径,您可以简单地cd到它,然后正常处理

所以你只需要做

 scriptDir=$(dirname -- "$0") cd -- "$scriptDir" 

但是,这仍然是一个黑客,你可能应该想办法用绝对路径工作