运行 与当前脚本同目录下的一个脚本

Run a script in the same directory as the current script

我在同一文件夹中有两个 Bash 脚本(由下载整个存储库的用户保存在某处):

两个脚本应该在同一个目录下。我需要第一个脚本来调用第二个,但是有两个问题:

  1. 知道当前工作目录对我来说毫无用处,因为我不知道用户是如何执行第一个脚本的(可能是 /usr/bin/script.sh./script.sh,也可能是../Downloads/repo/scr/script.sh)
  2. 脚本 script.sh 将在调用 helper.sh 之前更改到不同的目录。

我绝对可以拼凑 Bash 通过将 the current directory 存储在一个变量中来做到这一点,但是对于我认为是一个非常常见和简单的任务来说,该代码似乎不必要地复杂。

是否有一种标准方法可以从 script.sh可靠地 调用 helper.sh?并且可以在任何 Bash 支持的操作系统中运行吗?

由于 [=12=] 包含脚本的完整路径 运行,您可以使用 dirname 来获取脚本的路径:

#!/bin/bash

script_name=[=10=]
script_full_path=$(dirname "[=10=]")

echo "script_name: $script_name"
echo "full path: $script_full_path"

因此,如果您将其存储在 /tmp/a.sh 中,那么您将看到如下输出:

$ /tmp/a.sh
script_name: /tmp/a.sh
full path: /tmp

所以

  1. Knowing the current working directory is useless to me, because I don't know how the user is executing the first script (could be with /usr/bin/script.sh, with ./script.sh, or it could be with ../Downloads/repo/scr/script.sh)

使用 dirname "[=18=]" 将允许您跟踪原始路径。

  1. The script script.sh will be changing to a different directory before calling helper.sh.

同样,由于您在 [=12=] 中有路径,您可以 cd 返回它。

[=12=] 被许多开发者认为是 and fragile。我找到了另一个解决方案,它对于 bash 脚本链和 source.

是安全的

如果 a.sh 需要使用 child bash 进程执行 b.sh(位于同一文件夹中):

#!/bin/bash
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
bash ${__dir}/b.sh

如果a.sh需要使用相同 bash进程执行b.sh(位于同一文件夹):

#!/bin/bash
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source ${__dir}/b.sh

Is there a standard way to reliably call helper.sh from within script.sh? And will work in any Bash-supported operating system?

大多数情况下,当helper.shscript.sh在同一目录时,您可以使用在 script.sh 命令中:

. ${0%/*}/helper.sh

解释:
[=18=] 存储您的进程的名称(在 大多数情况下 它是您脚本的完整路径)。
${parameter%word} 从变量 $parameter 中删除后缀模式 word(在上面的命令中,它从存储在变量 [=18=] 中的完整路径中删除文件名 /*)。

如果由于某些原因(在其他答案中描述)您不想使用[=18=],您可以使用 $BASH_SOURCE 代替:

. ${BASH_SOURCE%/*}/helper.sh

如果你愿意,你可以使用 source 而不是 .:

source ${BASH_SOURCE%/*}/helper.sh

对我来说,这是实现目标最简单的方法。

您可以使用 [=11=] 变量。但这并不像获取当前脚本名称那么简单:

d=${0%/*}
[ x"$d" = x"[=10=]" ] && d=.   # portable variant, use [[ ...]] in bash freely
readonly d                 # optional, for additional safety

# ... later on
. "$d"/helper.sh

这在 set -e 情况下也很有效。