如何在"$0"和之间做出选择"${BASH_SOURCE[0]}"
"$0"
"${BASH_SOURCE[0]}"
来自GNU的这个描述对我没有多大帮助。
BASH_SOURCE An array variable whose members are the source filenames where the corresponding shell function names in the FUNCNAME array variable are defined. The shell function ${FUNCNAME[$i]} is defined in the file ${BASH_SOURCE[$i]} and called from ${BASH_SOURCE[$i+1]}
注意:对于 符合 POSIX 的 解决方案,请参阅此答案。
${BASH_SOURCE[0]}(或更简单地说,$BASH_SOURCE[1] )在 所有 调用场景 中包含包含脚本的(可能是相对的)路径,尤其是当脚本是 source 时,这对于$0.
${BASH_SOURCE[0]}
$BASH_SOURCE
$0
此外,正如Charles Duffy指出的那样,调用者$0可以将其设置为 任意 值。 另一方面,如果不涉及命名文件,$BASH_SOURCE 则可以为空; 例如: echo 'echo "[$BASH_SOURCE]"' | bash
echo 'echo "[$BASH_SOURCE]"' | bash
以下示例说明了这一点:
脚本foo:
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 特定的。
BASH_SOURCE
[1] 可选读物:${BASH_SOURCE[0]}对比$BASH_SOURCE:
Bash 允许您使用 标量0表示法来引用数组变量的 元素 :您可以编写;而不是写; 换句话说:如果您将变量引用 为标量 ,您将获得 index 处的元素。 ${arr[0]}``$arr 0
0
${arr[0]}``$arr
使用此功能会掩盖数组这一事实$arr,这就是流行的 shell-code linter shellcheck.net发出以下警告的原因(截至撰写本文时):
$arr
SC2128:扩展没有索引的数组只给出第一个元素。
附带说明:虽然此警告很有帮助,但它可能更精确,因为您不一定会得到第 一个 元素:它特别0是返回的索引处的元素,所以如果第一个元素具有更高的索引 -在 Bash 中是可能的 - 你会得到空字符串;试试'a[1]='hi'; echo "$a"'。 (相比之下,zsh叛徒确实 返回 第一个元素,而不管其索引如何)。
'a[1]='hi'; echo "$a"'
zsh
由于其晦涩难懂,您可能会选择避开此功能,但它的工作原理是可预测的,而且从实用的角度讲,您很少需要访问数组变量 以外 的索引。0``${BASH_SOURCE[@]}
0``${BASH_SOURCE[@]}
可选阅读,第 2 部分:在什么情况下,BASH_SOURCE数组变量实际上包含 多个 元素?:
BASH_SOURCE 如果涉及函数调用,则 只有多个条目,在这种情况下,它的元素与FUNCNAME包含 当前调用堆栈上的 所有函数名称的数组平行。
FUNCNAME
也就是说,在函数内部,${FUNCNAME[0]}包含执行函数的名称${BASH_SOURCE[0]},包含定义该函数的脚本文件的路径,${FUNCNAME[1]}包含调用当前执行函数的函数的名称(如果适用),等等上。
${FUNCNAME[0]}
${FUNCNAME[1]}
如果给定函数是直接从脚本文件的顶级范围调用的,该脚本文件$i在调用堆栈级别定义了该函数,则${FUNCNAME[$i+1]}包含:
$i
${FUNCNAME[$i+1]}
main(伪函数名称),如果脚本文件被 直接 调用(例如,./script)
main
./script
source(伪函数名称),如果脚本文件是 来源 (例如source ./script或. ./script)。
source
source ./script
. ./script