本文翻译自:Reliable way for a Bash script to get the full path to itself [duplicate]
This question already has an answer here: 这个问题已经在这里有了答案:
I have a Bash script that needs to know its full path. 我有一个Bash脚本,需要知道其完整路径。 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. 我只需要支持Bash,不需要sh,csh等。
What I've found so far: 到目前为止,我发现了什么:
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. 从地址中通过dirname $0
获取脚本的路径来获取Bash脚本的源目录的可接受答案,这很好,但是可能会返回相对路径(如.
),如果要更改,则是一个问题脚本中的目录,并且路径仍指向脚本的目录。 Still, dirname
will be part of the puzzle. dirname
仍然是难题的一部分。
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. Bash脚本在OS X上的绝对路径的可接受答案(特定 于OS X ,但无论如何答案均有效)提供了一个函数,该函数将测试以查看$0
是否是相对的,如果是相对的,则将$PWD
在其前面。 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. 但是结果仍然可以包含相对位(尽管总的来说是绝对的)—例如,如果脚本位于目录/usr/bin
中的t
,而您位于/usr
,则键入bin/../bin/t
要运行它(是的,这很麻烦),您最终将/usr/bin/../bin
作为脚本的目录路径。 Which works , but... 哪个可行 ,但是...
The readlink
solution on this page , which looks like this: 此页面上的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`
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). 但是readlink
并不是POSIX,显然,该解决方案依赖于GNU的readlink
,由于某些原因BSD的readlink
无法工作(我无法访问类似BSD的系统进行检查)。
So, various ways of doing it, but they all have their caveats. 因此,这样做的方法多种多样,但它们都有自己的警告。
What would be a better way? 有什么更好的方法? Where "better" means: “更好”是指:
参考:https://stackoom.com/question/K1ws/Bash脚本获取自身完整路径的可靠方法
I'm surprised that the realpath
command hasn't been mentioned here. 我很惊讶在这里没有提到realpath
命令。 My understanding is that it is widely portable / ported. 我的理解是,它可以广泛移植/移植。
Your initial solution becomes: 您最初的解决方案是:
SCRIPT=`realpath $0`
SCRIPTPATH=`dirname $SCRIPT`
And to leave symbolic links unresolved per your preference: 并根据您的喜好保留未解析的符号链接:
SCRIPT=`realpath -s $0`
SCRIPTPATH=`dirname $SCRIPT`
It does not use the -f
option in readlink, and it should therefore work on BSD/Mac OS X. 它不使用readlink中的-f
选项,因此它应在BSD / Mac OS X上运行。
.
dot operator) 源./script(由.
点运算符调用时) foo->dir1/dir2/bar bar->./../doe doe->script
当符号链接嵌套时,例如foo->dir1/dir2/bar bar->./../doe doe->script
I am looking for corner cases where this code does not work . 我正在寻找这种代码不起作用的极端情况 。 Please let me know. 请告诉我。
pushd . > /dev/null
SCRIPT_PATH="${BASH_SOURCE[0]}";
while([ -h "${SCRIPT_PATH}" ]); do
cd "`dirname "${SCRIPT_PATH}"`"
SCRIPT_PATH="$(readlink "`basename "${SCRIPT_PATH}"`")";
done
cd "`dirname "${SCRIPT_PATH}"`" > /dev/null
SCRIPT_PATH="`pwd`";
popd > /dev/null
echo "srcipt=[${SCRIPT_PATH}]"
echo "pwd =[`pwd`]"
The script must be on disk somewhere . 该脚本必须在磁盘上的某个位置 。 Let it be over a network. 让它通过网络。 If you try to run this script from a PIPE it will not work 如果尝试从PIPE运行此脚本,它将无法正常工作
wget -o /dev/null -O - http://host.domain/dir/script.sh |bash
Technically speaking, it is undefined. 从技术上讲,它是不确定的。 Practically speaking, there is no sane way to detect this. 实际上,没有理智的方法可以检测到这一点。 (A co-process can not access the environment of the parent.) (协同进程无法访问父级的环境。)
As realpath is not installed per default on my Linux system, the following works for me: 由于我的Linux系统上默认未安装realpath,因此以下内容适用于我:
SCRIPT="$(readlink --canonicalize-existing "$0")"
SCRIPTPATH="$(dirname "$SCRIPT")"
$SCRIPT
will contain the real file path to the script and $SCRIPTPATH
the real path of the directory containing the script. $SCRIPT
将包含$SCRIPT
的真实文件路径,而$SCRIPTPATH
将包含脚本的目录的真实路径。
Before using this read the comments of this answer . 在使用本文档之前,请先阅读本答案的注释。
I just had to revisit this issue today and found Get the source directory of a Bash script from within the script itself : 我今天只需要重新审视此问题,并发现从脚本本身中获取Bash脚本的源目录 :
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
There's more variants at the linked answer, eg for the case where the script itself is a symlink. 链接答案有更多变体,例如,脚本本身是符号链接的情况。
Use: 采用:
SCRIPT_PATH=$(dirname `which $0`)
which
prints to standard output the full path of the executable that would have been executed when the passed argument had been entered at the shell prompt (which is what $0 contains) which
打印到标准输出,将在传递的参数已经在shell提示符下(这是$ 0包含)已作出已执行的可执行文件的完整路径
dirname
strips the non-directory suffix from a file name. dirname
从文件名中dirname
非目录后缀。
Hence you end up with the full path of the script, no matter if the path was specified or not. 因此,无论是否指定了路径,您都将获得脚本的完整路径。