shell 脚本如何判断所在目录问题

2016-10-24 10:40:33来源:作者:星尘独奏曲人点击

这是某业务广泛的 QQ 群里的一次讨论,尘光大前辈问起都是怎么获取脚本所在绝对路径。

首先有同学表示可以使用 pwd 配合 $ 0 参数,但是很明显脚本执行的时候并不一定在当前 working dir,这就会带来一个明显的问题就是,如果执行的方式是 . / a .sh ,那么获取到的$0和 pwd 的结果才是相同的,否则就是不同的:

当然,可以说判断执行的方式,根据判断$0是否是绝对路径等方法可以区分这个情况,但是首先这样就变得麻烦,其次软链接的情况就不能通过这个判断,一个简单的验证:

尘光前辈关于软链接的实际应用的陈述:

~/bin/setup-firewall.sh -> /opt/gateway/bin/setup-firewall.sh 这种情况,如果是 ~/bin/setup-firewall.sh 这样运行的话,pwd的方案获取到的是 ~/bin/setup-firewall.sh,而不是 /opt/gateway,但是我显然不关心 ~/bin/ 这个目录,得到一个软链没有实际作用。

比如可能是这样的:

/usr/bin/gcc -> /etc/alternatives/gcc -> /usr/bin/gcc-xxx

或者更远的:

/usr/bin/editor -> /etc/alternatives/editor -> /usr/bin/some-editor -> /usr/bin/some-editor-$version

所以最简洁的就是 readlink -f $(which $0) ,readlink -f 可以递归的跟软链。

实际上像偷懒也不是不行,先 cd 可以简单的解决这个问题,但是如果目的是为了在各个地方都能直接运行脚本,综合来看简洁优雅的办法是 __script_base = $ ( dirname $ ( readlink - f $ ( which $ 0 ) ) )

然而前辈在 Mac 上第一次跑就挂掉了,因为 Mac 的 readlink 没有 -f 递归功能

依旧是一个简单的验证:

至于尘光前辈提到的 Mac 上 readlink 没有 -f 参数,实际上 homebrew 里提供了 GNU coreutils,为避免和 BSD 风格的命令产生冲突,安装后的 coreutils 命令全部需要加 g 前缀, brew install coreutils 后使用 greadlink 或者 grealpath 即可;如果需要使用 GNU 风格的命令直接替代系统自带命令,根据 homebrew 的提示,自行添加 PATH 即可: export PATH = "/usr/local/opt/coreutils/libexec/gnubin:$PATH"

关于这个问题,也可以参见阅读 http://stackoverflow.com/questions/4774054/reliable-way-for-a-bash-script-to-get-the-full-path-to-itself 提供了很多神奇的思路。

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台