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
是否看起来是相对的,如果是这样,则将其挂起$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).
推荐答案
这就是我想出的(加上 levigroker , 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).
这篇关于Bash脚本获取自身完整路径的可靠方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!