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

本文翻译自:Reliable way for a Bash script to get the full path to itself [duplicate]

This question already has an answer here: 这个问题已经在这里有了答案:

  • Get the source directory of a Bash script from within the script itself 62 answers 从脚本本身内部获取Bash脚本的源目录 62答案

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: 到目前为止,我发现了什么:

  1. 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仍然是难题的一部分。

  2. 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... 哪个可行 ,但是...

  3. 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: “更好”是指:

  • Gives me the absolute path. 给我绝对的道路。
  • Takes out funky bits even when invoked in a convoluted way (see comment on #2 above). 即使以卷积方式调用,也要取出时髦的位(请参阅上面的#2注释)。 (Eg, 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.). 仅依赖于Bash-ism或几乎可以肯定在* nix系统(GNU / Linux,BSD和类似BSD的系统,如OS X等)的大多数流行版本中使用的东西。
  • Avoids calling external programs if possible (eg, prefers Bash built-ins). 尽可能避免调用外部程序(例如,首选内置的Bash)。
  • ( 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). 更新 ,感谢抬起头, 至极 )它没有解决符号链接(其实,我倒是那种喜欢它,离开他们独自一人,但是这不是必须的)。

#1楼

参考:https://stackoom.com/question/K1ws/Bash脚本获取自身完整路径的可靠方法


#2楼

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`

#3楼

Get the absolute path of a shell script 获取shell脚本的绝对路径

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上运行。

Supports 支持

  • source ./script (When called by the . dot operator) 源./script(由.点运算符调用时)
  • Absolute path /path/to/script 绝对路径/ path / to / script
  • Relative path like ./script 相对路径,如./script
  • /path/dir1/../dir2/dir3/../script /path/dir1/../dir2/dir3/../script
  • When called from symlink 从symlink调用时
  • When symlink is nested eg) foo->dir1/dir2/bar bar->./../doe doe->script 当符号链接嵌套时,例如foo->dir1/dir2/bar bar->./../doe doe->script
  • When caller changes the scripts name 呼叫者更改脚本名称时

I am looking for corner cases where this code does not work . 我正在寻找这种代码不起作用的极端情况 Please let me know. 请告诉我。

Code

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`]"

Known issus 已知的issus

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.) (协同进程无法访问父级的环境。)


#4楼

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 . 在使用本文档之前,请先阅读本答案的注释。


#5楼

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. 链接答案有更多变体,例如,脚本本身是符号链接的情况。


#6楼

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. 因此,无论是否指定了路径,您都将获得脚本的完整路径。

你可能感兴趣的:(bash,path)