源 bash 脚本是否包含错误的 $BASH_SOURCE 值?

源 bash 脚本是否包含错误的 $BASH_SOURCE 值?

Linux 文档项目说:

当获取文件时(通过在命令行中键入源文件名或 . 文件名),文件中的代码行将被执行,就像它们在命令行中打印一样。这对于复杂的提示特别有用,可以将它们存储在文件中并通过获取它们所在的文件来调用。

我有三个脚本:test.shtest2.shcommon.shcommon.sh设置$me包含当前脚本基本名称的变量(使用${BASH_SOURCE[0]})。test.sh调用并source显示。调用并显示的内容。common.sh$metest2.shevalcommon.sh$me

==> common.sh <==
#!/bin/bash

realpath=$(realpath "${BASH_SOURCE[0]}")
me=$(basename "${realpath}")

==> test.sh <==
#!/bin/bash

source common.sh

echo "me: $me"

==> test2.sh <==
#!/bin/bash

common=$(cat common.sh)
eval "$common"

echo "me: $me"

运行时./test2.sh,输出为me: test2.sh.这是对的。

运行时./test.sh,输出为me: common.sh.为什么会这样呢?

编辑

Jeff Schaller 的答案是正确的,因为sourcing另一个脚本将该脚本的名称“取消”到数组$BASH_SOURCE。通过查看我能够实现我想要的最后的值在$BASH_SOURCE.见下文:

#!/bin/bash

declare -p BASH_SOURCE
bash_source_size="${#BASH_SOURCE[*]}"
realpath=$(realpath "${BASH_SOURCE[$bash_source_size-1]}")
me=$(basename "${realpath}")

答案1

test.sh调用时source,bash 显式地获取common.sh当前脚本,因此更新BASH_SOURCE变量。当test2.sh执行命令替换(可以是任何内容)和后续命令时eval,没有显式sourcing发生,因此 BASH_SOURCE 不受影响。

检测您的 shell 脚本

declare -p BASH_SOURCE行查看差异:

$ ./test.sh
declare -a BASH_SOURCE='([0]="common.sh" [1]="./test.sh")'
declare -a BASH_SOURCE='([0]="./test.sh")'
me: common.sh

对比:

$ ./test2.sh
declare -a BASH_SOURCE='([0]="./test2.sh")'
declare -a BASH_SOURCE='([0]="./test2.sh")'
me: test2.sh

在 中test2.sh,就 bash 所知,您运行了任意命令,即$(echo ls).

相关内容