我有一个 Bash 脚本,需要知道其完整路径。我正在尝试找到一种广泛兼容的方法,而不会以相对或时髦的路径结尾。我只需要支持 Bash,不需要 sh,csh 等。
到目前为止,我发现了什么:
从地址中通过dirname $0
获取 Bash 脚本的源目录的可接受答案,可以通过 dirname $ 0 获得脚本的路径,这很好,但是可能会返回相对路径(如.
),如果要更改,则是一个问题脚本中的目录,并且路径仍指向脚本的目录。 dirname
仍然是难题的一部分。
Bash 脚本在 OS X 上的绝对路径的可接受答案(特定于 OS X,但无论如何答案均有效)提供了一个函数,该函数将测试以查看$0
是否是相对的,如果是相对的,则将$PWD
到它之前。但是结果中仍然可以包含相对位(尽管总的来说是绝对的)—例如,如果脚本在目录/usr/bin
t
,而您在/usr
,则键入bin/../bin/t
要运行它(是的,那很麻烦),您最终将/usr/bin/../bin
作为脚本的目录路径。哪个可行,但是...
此页面上的readlink
解决方案,如下所示:
# Absolute path to this script. /home/user/bin/foo.sh
SCRIPT=$(readlink -f $0)
# Absolute path this script is in. /home/user/bin
SCRIPTPATH=`dirname $SCRIPT`
但是readlink
并不是 POSIX,显然,该解决方案依赖于 GNU 的readlink
,由于某些原因 BSD 的 readlink 不能工作(我无法访问类似 BSD 的系统进行检查)。
因此,有各种各样的方法,但是它们都有自己的警告。
有什么更好的方法? “更好” 是指:
这是我想出的(编辑:加上sfstewman , levigroker , Kyle Strand和Rob Kennedy提供的一些调整),这似乎基本上符合我的 “更好” 标准:
SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
那条SCRIPTPATH
线似乎特别绕行,但是我们需要它而不是SCRIPTPATH=`pwd`
才能正确处理空格和符号链接。
包含输出重定向( >/dev/null 2>&1
)处理罕见(?)情况,其中cd
可能会产生会干扰周围$( ... )
捕获的输出。 (如cd
被重写到也ls
的目录切换到它之后)。
还要注意,深奥的情况(例如,执行完全不是来自可访问文件系统中文件的脚本(完全有可能))不适合那里(或在我见过的任何其他答案中) )。
本--
后cd
和前"$0"
是万一目录开始了-
令我惊讶的是,这里没有提到realpath
我的理解是,它可以广泛移植 / 移植。
您的初始解决方案变为:
SCRIPT=`realpath $0`
SCRIPTPATH=`dirname $SCRIPT`
并根据您的喜好保留未解析的符号链接:
SCRIPT=`realpath -s $0`
SCRIPTPATH=`dirname $SCRIPT`
我发现在 Bash 中获得完整规范路径的最简单方法是使用cd
和pwd
:
ABSOLUTE_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$(basename "${BASH_SOURCE[0]}")"
使用${BASH_SOURCE[0]}
代替$0
会产生相同的行为,而不管脚本是作为<name>
还是source <name>
调用。