协慌网

登录 贡献 社区

Bash 脚本获取自身完整路径的可靠方法

我有一个 Bash 脚本,需要知道其完整路径。我正在尝试找到一种广泛兼容的方法,而不会以相对或时髦的路径结尾。我只需要支持 Bash,不需要 sh,csh 等。

到目前为止,我发现了什么:

  1. 从地址中通过dirname $0 获取 Bash 脚本的源目录的可接受答案,可以通过 dirname $ 0 获得脚本的路径,这很好,但是可能会返回相对路径(如. ),如果要更改,则是一个问题脚本中的目录,并且路径仍指向脚本的目录。 dirname仍然是难题的一部分。

  2. Bash 脚本在 OS X 上的绝对路径的可接受答案(特定于 OS X,但无论如何答案均有效)提供了一个函数,该函数将测试以查看$0是否是相对的,如果是相对的,则将$PWD到它之前。但是结果中仍然可以包含相对位(尽管总的来说是绝对的)—例如,如果脚本在目录/usr/bin t ,而您在/usr ,则键入bin/../bin/t要运行它(是的,那很麻烦),您最终将/usr/bin/../bin作为脚本的目录路径。哪个可行,但是...

  3. 此页面上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 的系统进行检查)。

因此,有各种各样的方法,但是它们都有自己的警告。

有什么更好的方法? “更好” 是指:

  • 给我绝对的道路。
  • 即使以卷积方式调用,也要取出时髦的位(请参见上面对#2 的评论)。 (例如,至少适当地规范化路径。)
  • 仅依赖于 Bash-ism 或几乎可以肯定在 * nix 系统(GNU / Linux,BSD 和类似 BSD 的系统,如 OS X 等)的大多数流行版本中使用的东西。
  • 尽可能避免调用外部程序(例如,首选内置 Bash)。
  • (已更新,感谢您的直觉。 )它不必解析符号链接(实际上,我宁愿它不理会它们,但这不是必须的)。

答案

这是我想出的(编辑:加上sfstewmanlevigrokerKyle StrandRob 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 中获得完整规范路径的最简单方法是使用cdpwd

ABSOLUTE_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$(basename "${BASH_SOURCE[0]}")"

使用${BASH_SOURCE[0]}代替$0会产生相同的行为,而不管脚本是作为<name>还是source <name>调用。