Bash 脚本获取自身完整路径的可靠方法 [英] Reliable way for a Bash script to get the full path to itself
问题描述
我有一个需要知道其完整路径的 Bash 脚本.我试图找到一种广泛兼容的方式来做到这一点,而不会以相对或看起来很时髦的路径结束.我只需要支持Bash,不需要sh、csh等
I have a Bash script that needs to know its full path. I'm trying to find a broadly-compatible way of doing that without ending up with relative or funky-looking paths. I only need to support Bash, not sh, csh, etc.
到目前为止我发现了什么:
What I've found so far:
从内部获取 Bash 脚本的源目录 解决了通过
dirname $0
获取脚本的路径,这很好,但可能会返回一个 relative 路径(如.
),如果您想更改脚本中的目录并让路径仍然指向脚本的目录,这是一个问题.尽管如此,dirname
将成为难题的一部分.
The accepted answer to Getting the source directory of a Bash script from within addresses getting the path of the script via
dirname $0
, which is fine, but that may return a relative path (like.
), which is a problem if you want to change directories in the script and have the path still point to the script's directory. Still,dirname
will be part of the puzzle.
Bash 脚本绝对路径与 OS X 的公认答案 (特定于 OS X,但无论如何答案都有效) 提供了一个函数来测试 $0
是否看起来是相对的,如果是,则将预先-pend $PWD
到它.但是结果中仍然可以包含相对位(尽管总体上是绝对的) —例如,如果脚本位于 /usr/bin
目录中的 t
而你在 /usr
中,你输入 bin/../bin/t
来运行它(是的,这很复杂),你最终将 /usr/bin/../bin
作为脚本的目录路径.哪个有效,但是...
The accepted answer to Bash script absolute path with OS X (OS X specific, but the answer works regardless) gives a function that will test to see if $0
looks relative and if so will pre-pend $PWD
to it. But the result can still have relative bits in it (although overall it's absolute) — for instance, if the script is t
in the directory /usr/bin
and you're in /usr
and you type bin/../bin/t
to run it (yes, that's convoluted), you end up with /usr/bin/../bin
as the script's directory path. Which works, but...
readlink
解决方案 在此页面上,如下所示:
The readlink
solution on this page, which looks like this:
# 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 由于某种原因无法工作(我无法访问 BSD- 类似系统检查).
But readlink
isn't POSIX and apparently the solution relies on GNU's readlink
where BSD's won't work for some reason (I don't have access to a BSD-like system to check).
所以,这样做的方法多种多样,但它们都有自己的警告.
So, various ways of doing it, but they all have their caveats.
什么是更好的方法?更好"的意思是:
What would be a better way? Where "better" means:
- 给我绝对路径.
- 即使在以复杂的方式调用时也会取出时髦的位(请参阅上面对 #2 的评论).(例如,至少适度规范化路径.)
- 仅依赖 Bash 主义或几乎肯定会依赖*nix 系统(GNU/Linux、BSD 和类似 BSD 的系统,如 OS X 等)的大多数流行风格的东西.
- 尽可能避免调用外部程序(例如,更喜欢 Bash 内置程序).
- (更新,感谢提醒,wich)它没有解决符号链接(事实上,我更喜欢不理会它们,但这不是必需的).
- Gives me the absolute path.
- Takes out funky bits even when invoked in a convoluted way (see comment on #2 above). (E.g., at least moderately canonicalizes the path.)
- Relies only on Bash-isms or things that are almost certain to be on most popular flavors of *nix systems (GNU/Linux, BSD and BSD-like systems like OS X, etc.).
- Avoids calling external programs if possible (e.g., prefers Bash built-ins).
- (Updated, thanks for the heads up, wich) It doesn't have to resolve symlinks (in fact, I'd kind of prefer it left them alone, but that's not a requirement).
推荐答案
这是我想出的(加上一些由 sfstewman、levigroker、Kyle Strand 和 Rob Kennedy),这似乎最适合我的更好"标准:
Here's what I've come up with (edit: plus some tweaks provided by sfstewman, levigroker, Kyle Strand, and Rob Kennedy), that seems to mostly fit my "better" criteria:
SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
SCRIPTPATH
行看起来特别迂回,但我们需要它而不是 SCRIPTPATH=`pwd`
以便正确处理空格和符号链接.
That SCRIPTPATH
line seems particularly roundabout, but we need it rather than SCRIPTPATH=`pwd`
in order to properly handle spaces and symlinks.
包含输出重定向 (>/dev/null 2>&1
) 可处理罕见的 (?) 情况,其中 cd
可能会产生会干扰的输出与周围的 $( ... )
捕获.(例如 cd
也被覆盖为 ls
目录 切换到它之后.)
The inclusion of output redirection (>/dev/null 2>&1
) handles the rare(?) case where cd
might produce output that would interfere with the surrounding $( ... )
capture. (Such as cd
being overridden to also ls
a directory after switching to it.)
另请注意,深奥的情况,例如执行根本不是来自可访问文件系统中的文件的脚本(这是完全可能的),并没有迎合那里(或在我的任何其他答案中)见过).
Note also that esoteric situations, such as executing a script that isn't coming from a file in an accessible file system at all (which is perfectly possible), is not catered to there (or in any of the other answers I've seen).
cd
之后和 $0"
之前的 --
是在目录以 -
开头的情况下代码>.
The --
after cd
and before "$0"
are in case the directory starts with a -
.
这篇关于Bash 脚本获取自身完整路径的可靠方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!