在$ 0和BASH_SOURCE之间选择


117

如何在"$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]}

BASH_SOURCE是在bash-3.0-alpha中添加的。您可能没有它,具体取决于您的测试方案。我在早期的Solaris和OS X上都找不到它。另请参见return:只能从 U&L.SE上的函数或源脚本中“返回”
jww '18 -10-5

Answers:


174

注意:有关POSIX兼容解决方案,请参见此答案

${BASH_SOURCE[0]}(或更简单地说,$BASH_SOURCE[1] )在所有调用场景中包含包含脚本的(可能是相对的)路径,尤其是在脚本源时,该路径也不适用$0

此外,正如查尔斯·达菲Charles Duffy)所指出的,调用者$0可以将其设置为任意值。
另一方面,如果不涉及命名文件,$BASH_SOURCE 则可以为空;否则为空。例如:
echo 'echo "[$BASH_SOURCE]"' | bash

以下示例说明了这一点:

剧本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

击允许你参考元件0的的阵列变量使用标量表示法:代替书写的${arr[0]},可以编写$arr; 换句话说:如果您将变量当作标量来引用,则元素位于index处0

使用此功能可以掩盖$arr一个数组的事实,这就是为什么流行的shell代码linter shellcheck.net发出以下警告的原因(截至撰写本文时):

SC2128:扩展没有索引的数组只会得到第一个元素。

附带说明:虽然此警告很有用,但它可能更精确,因为您不一定会获得第一个元素:特别0是返回索引处的元素,因此,如果第一个元素具有更高的索引-在Bash中是可能的-您将获得空字符串;尝试一下'a[1]='hi'; echo "$a"'
(相比之下,zsh,曾经的叛徒,确实返回的第一个元素,不管其索引)。

您可能会因为其晦涩难懂而选择避开此功能,但是它可以预见地工作,并且从实用的角度来说,您几乎不需要访问数组变量以外的其他索引。0${BASH_SOURCE[@]}


所以$ BASH_SOURCE更通用并且可以在更多情况下使用?
亚历山大·米尔斯

2
@AlexanderMills是的,如果您使用的是Bash,$BASH_SOURCE则是更好的选择。
mklement0

18

这些脚本可能有助于说明。外部脚本调用中间脚本,中间脚本调用内部脚本:

$ cat outer.sh
#!/usr/bin/env bash
./middle.sh
$ cat middle.sh
#!/usr/bin/env bash
./inner.sh
$ cat inner.sh
#!/usr/bin/env bash
echo "\$0 = '$0'"
echo "\${BASH_SOURCE[0]} = '${BASH_SOURCE[0]}'"
echo "\${BASH_SOURCE[1]} = '${BASH_SOURCE[1]}'"
echo "\${BASH_SOURCE[2]} = '${BASH_SOURCE[2]}'"
$ ./outer.sh
$0 = './inner.sh'
$BASH_SOURCE[0] = './inner.sh'
$BASH_SOURCE[1] = ''
$BASH_SOURCE[2] = ''

但是,如果我们将脚本调用更改为source语句:

$ cat outer.sh
#!/usr/bin/env bash
source ./middle.sh
$ cat middle.sh
#!/usr/bin/env bash
source ./inner.sh
$ cat inner.sh
#!/usr/bin/env bash
echo "\$0 = '$0'"
echo "\${BASH_SOURCE[0]} = '${BASH_SOURCE[0]}'"
echo "\${BASH_SOURCE[1]} = '${BASH_SOURCE[1]}'"
echo "\${BASH_SOURCE[2]} = '${BASH_SOURCE[2]}'"
$ ./outer.sh
$0 = './outer.sh'
$BASH_SOURCE[0] = './inner.sh'
$BASH_SOURCE[1] = './middle.sh'
$BASH_SOURCE[2] = './outer.sh'

1

对于可移植性,请${BASH_SOURCE[0]}在定义时使用,$0否则使用。那给

${BASH_SOURCE[0]:-$0}

值得注意的是,在zsh中,即使脚本是sourced ,$ 0的确包含正确的文件路径。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.