当获取文件时(通过在命令行中键入源文件名或 . 文件名),文件中的代码行将被执行,就像它们在命令行中打印一样。这对于复杂的提示特别有用,可以将它们存储在文件中并通过获取它们所在的文件来调用。
我有三个脚本:test.sh
、test2.sh
和common.sh
。common.sh
设置$me
包含当前脚本基本名称的变量(使用${BASH_SOURCE[0]}
)。test.sh
调用并source
显示。调用并显示的内容。common.sh
$me
test2.sh
eval
common.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)
.