Note: For a POSIX-compliant solution, see this answer.
${BASH_SOURCE[0]}
(or, more simply, $BASH_SOURCE
[1]
) contains the (potentially relative) path of the containing script in all invocation scenarios, notably also when the script is sourced, which is not true for $0
.
Furthermore, as Charles Duffy points out, $0
can be set to an arbitrary value by the caller.
On the flip side, $BASH_SOURCE
can be empty, if no named file is involved; e.g.:
echo 'echo "[$BASH_SOURCE]"' | bash
下面的例子说明了这一点:
Script foo
:
#!/bin/bash
echo "[$0] vs. [${BASH_SOURCE[0]}]"
$ bash ./foo
[./foo] vs. [./foo]
$ ./foo
[./foo] vs. [./foo]
$ . ./foo
[bash] vs. [./foo]
$0
是 POSIX shell 规范的一部分,而BASH_SOURCE
顾名思义,是 Bash 特有的。
[1] 可选阅读:${BASH_SOURCE[0]}
vs. $BASH_SOURCE
:
Bash 允许你引用元素0
of an array变量使用scalar记法:代替书写${arr[0]}
, 你可以写$arr
;换句话说:如果您引用变量就好像它是一个标量,你得到索引处的元素0
.
使用此功能掩盖了这样一个事实:$arr
是一个数组,这就是流行 shell-code linter 的原因shellcheck.net发出以下警告(截至撰写本文时):
SC2128:扩展没有索引的数组仅给出第一个元素。
旁注:虽然此警告很有帮助,但它可以更准确,因为您不一定会得到firstelement:具体是索引处的元素0
返回,因此如果第一个元素具有更高的索引(这在 Bash 中是可能的),您将得到空字符串;尝试a[1]='hi'; echo "$a"
.
(相比之下,zsh
,永远的叛徒,回归all元素作为单个字符串,用第一个字符分隔。存储在$IFS
,这是一个space默认情况下)。
由于它的晦涩难懂,您可能会选择避开此功能,但它的工作原理是可以预见的,而且,务实地说,您很少(如果有的话)需要访问索引other than 0
数组变量的${BASH_SOURCE[@]}
.
可选阅读,第 2 部分:在什么条件下BASH_SOURCE
数组变量实际上包含multiple元素?:
BASH_SOURCE
只有多个条目如果涉及函数调用,在这种情况下它的元素平行于FUNCNAME
包含所有函数名称的数组当前位于调用堆栈上.
也就是说,在一个函数内部,${FUNCNAME[0]}
包含执行函数的名称,以及${BASH_SOURCE[0]}
包含定义该函数的脚本文件的路径,${FUNCNAME[1]}
包含调用当前正在执行的函数的函数名称(如果适用),等等。
如果给定函数是直接从定义该函数的脚本文件中的顶级作用域调用的$i
调用堆栈的,${FUNCNAME[$i+1]}
包含:
-
main
(伪函数名),如果调用脚本文件directly (e.g., ./script
)
-
source
(伪函数名),如果脚本文件是sourced (e.g. source ./script
or . ./script
).