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

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

$ ./application

当前回答

這是解決方案 e-satis 和 3bcdnlklvc04a 在他們的答案中指出的輕微改訂:

SCRIPT_DIR=''
pushd "$(dirname "$(readlink -f "$BASH_SOURCE")")" > /dev/null && {
    SCRIPT_DIR="$PWD"
    popd > /dev/null
}

这应该在他们列出的所有情况下仍然有效。

这将防止一个失败的冲动之后的Popd. 感谢控制台。

其他回答

這是我多年來創造的,用作我的Bash寫作的標題:

## BASE BRAIN - Get where you're from and who you are.
MYPID=$$
ORIGINAL_DIR="$(pwd)" # This is not a hot air balloon ride..
fa="$0" # First Assumption
ta= # Temporary Assumption
wa= # Weighed Assumption
while true; do
    [ "${fa:0:1}" = "/" ] && wa=$0 && break
    [ "${fa:0:2}" = "./" ] && ta="${ORIGINAL_DIR}/${fa:2}" && [ -e "$ta" ] && wa="$ta" && break
    ta="${ORIGINAL_DIR}/${fa}" && [ -e "$ta" ] && wa="$ta" && break
done
SW="$wa"
SWDIR="$(dirname "$wa")"
SWBIN="$(basename "$wa")"
unset ta fa wa
( [ ! -e "$SWDIR/$SWBIN" ] || [ -z "$SW" ] ) && echo "I could not find my way around :( possible bug in the TOP script" && exit 1

此时此刻,您的变量 SW、SWDIR 和 SWBIN 包含您需要的内容。

我会用这样的东西:

# Retrieve the full pathname of the called script
scriptPath=$(which $0)

# Check whether the path is a link or not
if [ -L $scriptPath ]; then

    # It is a link then retrieve the target path and get the directory name
    sourceDir=$(dirname $(readlink -f $scriptPath))

else

    # Otherwise just get the directory name of the script path
    sourceDir=$(dirname $scriptPath)

fi

我已经比较了许多答案,并出现了一些更紧凑的解决方案. 这些似乎处理所有疯狂的边缘案例,从你最喜欢的组合:

绝对路径或相对路径 文件和目录 软链接 作为脚本, bash 脚本, bash -c 脚本, 源脚本, 或. 脚本 空间, 标签, 新闻, Unicode, 等 在目录和 / 或 文件名 Filenames 从一个 hyphen

如果您正在运行从Linux,似乎使用proc操作是找到目前运行脚本的完全解决源的最佳解决方案(在互动会议中,链接点到相应的 /dev/pts/X):

resolved="$(readlink /proc/$$/fd/255 && echo X)" && resolved="${resolved%$'\nX'}"

absolute_path=$(readlink -e -- "${BASH_SOURCE[0]}" && echo x) && absolute_path=${absolute_path%?x}
dir=$(dirname -- "$absolute_path" && echo x) && dir=${dir%?x}
file=$(basename -- "$absolute_path" && echo x) && file=${file%?x}

ls -l -- "$dir/$file"
printf '$absolute_path: "%s"\n' "$absolute_path"

$_ 值得提到为 $0 的替代品。 如果您正在运行来自 Bash 的脚本,可将接受的答案缩短到:

DIR="$( dirname "$_" )"

请注意,这应该是您的脚本中的第一个声明。

pushd . > '/dev/null';
SCRIPT_PATH="${BASH_SOURCE[0]:-$0}";

while [ -h "$SCRIPT_PATH" ];
do
    cd "$( dirname -- "$SCRIPT_PATH"; )";
    SCRIPT_PATH="$( readlink -f -- "$SCRIPT_PATH"; )";
done

cd "$( dirname -- "$SCRIPT_PATH"; )" > '/dev/null';
SCRIPT_PATH="$( pwd; )";
popd  > '/dev/null';

它适用于所有版本,包括

当通过多个深度软链接呼叫时,当文件时,当脚本被命令“源”称为. (dot) 操作员时,当 arg $0 从呼叫器修改时,“./script” “/full/path/to/script” “/some/path/../../other/path/script” “./some/folder/script”

否则,如果Bash脚本本身是一个相对的Symlink,你想跟随它并返回链接到脚本的完整路径:

pushd . > '/dev/null';
SCRIPT_PATH="${BASH_SOURCE[0]:-$0}";

while [ -h "$SCRIPT_PATH" ];
do
    cd "$( dirname -- "$SCRIPT_PATH"; )";
    SCRIPT_PATH="$( readlink -f -- "$SCRIPT_PATH"; )";
done

cd "$( dirname -- "$SCRIPT_PATH"; )" > '/dev/null';
SCRIPT_PATH="$( pwd; )";
popd  > '/dev/null';

SCRIPT_PATH 以完整的路径提供,无论它是如何称呼的。

只需确保您在脚本开始时找到此处。