我如何找到一个Bash脚本位于该脚本内部的目录的路径?

我想用Bash脚本作为另一个应用程序的启动器,我想将工作目录更改为Bash脚本所在的目录,所以我可以在该目录中的文件上运行,如下:

$ ./application

当前回答

没有百分之百可携带和可靠的方式来要求一个路径到当前的脚本目录,特别是在不同背景,如Cygwin,MinGW,MSYS,Linux等之间,这个问题没有正确和完全解决在Bash的年龄。

在源命令的情况下,我建议用这样的东西取代源命令:

function include()
{
  if [[ -n "$CURRENT_SCRIPT_DIR" ]]; then
    local dir_path=... get directory from `CURRENT_SCRIPT_DIR/$1`, depends if $1 is absolute path or relative ...
    local include_file_path=...
  else
    local dir_path=... request the directory from the "$1" argument using one of answered here methods...
    local include_file_path=...
  fi
  ... push $CURRENT_SCRIPT_DIR in to stack ...
  export CURRENT_SCRIPT_DIR=... export current script directory using $dir_path ...
  source "$include_file_path"
  ... pop $CURRENT_SCRIPT_DIR from stack ...
}

从现在开始,使用包括(...)是基于以前的CURRENT_SCRIPT_DIR在你的脚本。

我自己最接近这一点的实施: https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/bash/tacklelib/bash_tacklelib https://github.com/andry81/tacklelib/tree/trunk/bash/tacklelib/bash_tacklelib

(搜索 tkl_include 函数)

其他回答

好吧,如果在路上,字母和字母只是不会切断它,走路是艰难的(如果父母没有出口PATH?!)。

然而,盾牌必须对其脚本有一个开放的手稿,而在Bash手稿是#255。

SELF=`readlink /proc/$$/fd/255`

为我工作。

没有<unk>(除了<unk>)和可以处理“陌生人”名称的形式,如那些有新闻,因为有些人会声称:

IFS= read -rd '' DIR < <([[ $BASH_SOURCE != */* ]] || cd "${BASH_SOURCE%/*}/" >&- && echo -n "$PWD")

如果不是由父母脚本来源,而不是同链接,0美元就足够了:

script_path="$0"

如果源于父母脚本而不是同链接,请使用 $BASH_SOURCE 或 ${BASH_SOURCE[0]}:

script_path="$BASH_SOURCE"

如果是同链接,请使用 $BASH_SOURCE 与 realpath 或 readlink -f 获取真正的文件路径:

script_path="$(realpath "$BASH_SOURCE")"

此外,路径或 readlink -f 返回绝对路径。

要获取脚本的目录,使用 dirname:

script_directory="$(dirname "$script_path")"

笔记

对于 MacOS 而言,请在这里或在这里找到一个替代路径或阅读链接 -f. 要使代码与不为 Bash 的支柱兼容,请使用 ${var-string} 参数扩展。

下面是一个命令,在Bash或zsh下工作,以及是否单独执行或源:

[ -n "$ZSH_VERSION" ] && this_dir=$(dirname "${(%):-%x}") \
    || this_dir=$(dirname "${BASH_SOURCE[0]:-$0}")

它是如何工作的

Fallback 替代操作员:

% x=ok
% echo "${x}"
ok

% echo "${x:-fallback}"
ok

% x=
% echo "${x:-fallback}"
fallback

% y=yvalue
% echo "${x:-$y}"
yvalue

此分類上一篇: %x prompt escape code

接下来,我们将引入即时逃避代码,一个 zsh-only 功能. 在 zsh 中, %x 将扩展到文件的路径,但通常只有在进行即时行扩展时。

% cat apath/test.sh
fpath=%x
echo "${(%)fpath}"

% source apath/test.sh
apath/test.sh

% cd apath
% source test.sh
test.sh

% cat test.sh
echo "${(%):-%x}"

% source test.sh
test.sh

请注意,我们通常会把变量名称放在(%)和(%)之间,但我们留下了白色。

我们可能已经使用打印 -P %x 以获得相同的文件路径,有更少的黑客,但在我们的情况下,我们需要将其作为一个论点转到一个字符串,这将需要一个开始一个新的字符串的顶部:

% cat apath/test.sh
dirname "$(print -P %x)"  # $(...) runs a command in a new process
dirname "${(%):-%x}"

% source apath/test.sh
apath
apath

显然,黑客的方式既更有效又更简短。

下面是简单而正确的方式:

actual_path=$(readlink -f "${BASH_SOURCE[0]}")
script_dir=$(dirname "$actual_path")

解释:

${BASH_SOURCE[0]} - 完整的路径到脚本. 这个值将是正确的,即使脚本是源,例如源 <(echo 'echo $0') 打印 bash,同时取代它为 ${BASH_SOURCE[0]} 将打印整个路径的脚本。