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

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

$ ./application

当前回答

您可以使用 $BASH_SOURCE:

#!/usr/bin/env bash

scriptdir="$( dirname -- "$BASH_SOURCE"; )";

请注意,您需要使用 #!/bin/bash 而不是 #!/bin/sh 因为它是一个 Bash 扩展。

其他回答

$(dirname "$(readlink -f "$BASH_SOURCE")")

此单行在 Cygwin 上工作,即使脚本已被从 Windows 称为 bash -c <script>:

set mydir="$(cygpath "$(dirname "$0")")"

目前的任何解决方案都没有工作,如果在目录名称结束时有任何新字符 - 它们将被命令替代器切断。 要在此周围工作,您可以在命令替代器中添加一个非新字符,然后切断该字符:

dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd && echo x)"
dir="${dir%x}"

這保護兩個非常常見的情況:事故和破壞. 一個劇本不應該以不可預測的方式失敗,只是因為有人,在某個地方,做了一個 mkdir $ '\n'.

这是令人不安的,我发现的唯一一个线路,它在Linux和macOS工作,当执行的脚本是一个同步链接:

SCRIPT_DIR=$(python -c "import os; print(os.path.dirname(os.path.realpath('${BASH_SOURCE[0]}')))")

或,类似,使用Python3 pathlib模块:

SCRIPT_DIR=$(python3 -c "from pathlib import Path; print(Path('${BASH_SOURCE[0]}').resolve().parent)")

在Linux和macOS上进行测试,并与其他解决方案进行比较: https://gist.github.com/ptc-mrucci/61772387878ed53a6c717d51a21d9371

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

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

解释:

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