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

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

$ ./application

当前回答

以下是获取脚本信息的简短方式:

文件和文件:

    Script: "/tmp/src dir/test.sh"
    Calling folder: "/tmp/src dir/other"

使用这些命令:

    echo Script-Dir : `dirname "$(realpath $0)"`
    echo Script-Dir : $( cd ${0%/*} && pwd -P )
    echo Script-Dir : $(dirname "$(readlink -f "$0")")
    echo
    echo Script-Name : `basename "$(realpath $0)"`
    echo Script-Name : `basename $0`
    echo
    echo Script-Dir-Relative : `dirname "$BASH_SOURCE"`
    echo Script-Dir-Relative : `dirname $0`
    echo
    echo Calling-Dir : `pwd`

我得到了这个结果:

     Script-Dir : /tmp/src dir
     Script-Dir : /tmp/src dir
     Script-Dir : /tmp/src dir

     Script-Name : test.sh
     Script-Name : test.sh

     Script-Dir-Relative : ..
     Script-Dir-Relative : ..

     Calling-Dir : /tmp/src dir/other

此分類上一篇: https://pastebin.com/J8KjxrPF

其他回答

如果不是由父母脚本来源,而不是同链接,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本身以外的任何东西,也不会破坏任何底层。

首先,使用模式替代替代不以 / (即相对路径) 以 $ PWD/. 因为我们使用替代替代相匹配的第一个字符为 $ 0,我们也必须添加它回来(${0:0:1} 在替代中)。

现在我们有一个完整的路径到脚本;我们可以通过删除最后的 / 和随后的任何东西(即脚本名称)来获得目录。

#!/bin/bash

BIN=${0/#[!\/]/"$PWD/${0:0:1}"}
DIR=${BIN%/*}

cd "$DIR"

如果您的脚本可以源于而不是执行,您可以将 $0 取代 ${BASH_SOURCE[0]},例如:

BIN=${BASH_SOURCE[0]/#[!\/]/"$PWD/${BASH_SOURCE[0]:0:1}"}

这将为可执行的脚本工作,它更长,但更多。

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

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

在我看来,最合适的解决方案是:

"$( cd "$( echo "${BASH_SOURCE[0]%/*}" )"; pwd )"

使用 dirname、 readlink 和 basename 最终会导致兼容性问题,所以如果可能的话最好避免。

dirname ${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}

如果您想跟随同步链接,请使用您上面的路径上的阅读链接,重复或非重复。

#
# Location: test1/test2/test_script.sh
#
echo $0
echo $_
echo ${BASH_SOURCE}
echo ${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}

cur_file="${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
cur_dir="$(dirname "${cur_file}")"
source "${cur_dir}/func_def.sh"

function test_within_func_inside {
    echo ${BASH_SOURCE}
    echo ${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}
}

echo "Testing within function inside"
test_within_func_inside

echo "Testing within function outside"
test_within_func_outside

#
# Location: test1/test2/func_def.sh
#
function test_within_func_outside {
    echo ${BASH_SOURCE}
    echo ${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}
}

BASH - 来源

一个序列变量,其成员是源文件名,在 FUNCNAME序列变量中定义了相应的序列函数名称。

功能

这个变量可以使用 BASH_LINENO 和 BASH_SOURCE. FUNCNAME 的每个元素都有相应的元素在 BASH_LINENO 和 BASH_SOURCE 描述呼叫板. 例如, ${FUNCNAME[$i]} 被呼叫从文件 ${BASH_SOURCE[$i+1]} 到线号 ${BASH_LINENO[$i]}。

(源:Bash手册)