bash 在 $0 和 BASH_SOURCE 之间选择

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35006457/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 22:10:52  来源:igfitidea点击:

choosing between $0 and BASH_SOURCE

bash

提问by H2ONaCl

How does one choose between "$0"and "${BASH_SOURCE[0]}"

如何在"$0"和之间选择"${BASH_SOURCE[0]}"

This description from GNUdidn't help me much.

来自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]}

回答by mklement0

Note: For a POSIX-compliant solution, see this answer.

注意:有关符合 POSIX 的解决方案,请参阅此答案

${BASH_SOURCE[0]}(or, more simply, $BASH_SOURCE[1]) contains the (potentially relative) path of the containing script in allinvocation scenarios, notably also when the script is sourced, which is not true for $0.

${BASH_SOURCE[0]}(或者,更简单地说,$BASH_SOURCE[1])包含所有调用场景中包含脚本的(可能是相对的)路径,特别是当脚本是source 时,这对于$0.

Furthermore, as Charles Duffypoints out, $0can be set to an arbitraryvalue by the caller.
On the flip side, $BASH_SOURCEcanbe empty, if no named file is involved; e.g.:
echo 'echo "[$BASH_SOURCE]"' | bash

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

The following example illustrates this:

以下示例说明了这一点:

Script foo:

脚本foo

#!/bin/bash
echo "[
$ bash ./foo
[./foo] vs. [./foo]

$ ./foo
[./foo] vs. [./foo]

$ . ./foo
[bash] vs. [./foo]
] vs. [${BASH_SOURCE[0]}]"


$ cat outer.sh
#!/usr/bin/env bash
./middle.sh

$0is part of the POSIX shell specification, whereas BASH_SOURCE, as the name suggests, is Bash-specific.

$0是 POSIX shell 规范的一部分,而BASH_SOURCE,顾名思义,是 Bash 特定的。



[1] Optional reading: ${BASH_SOURCE[0]}vs. $BASH_SOURCE:

[1]可选读物:${BASH_SOURCE[0]}vs.$BASH_SOURCE

Bash allows you to reference element 0of an arrayvariable using scalarnotation: instead of writing ${arr[0]}, you can write $arr; in other words: if you reference the variable as if it were a scalar, you get the element at index 0.

击允许你参考元件0的的阵列变量使用标量表示法:代替书写的${arr[0]},可以编写$arr; 换句话说:如果你像引用一个 scalar 一样引用变量,你就会得到 index 处的元素0

Using this feature obscures the fact that $arris an array, which is why popular shell-code linter shellcheck.netissues the following warning (as of this writing):

使用此功能掩盖了$arr数组的事实,这就是流行的 shell-code linter shellcheck.net发出以下警告的原因(在撰写本文时):

SC2128: Expanding an array without an index only gives the first element.

SC2128:扩展没有索引的数组只给出第一个元素。

On a side note: While this warning is helpful, it could be more precise, because you won't necessarily get the firstelement: It is specifically the element at index 0that is returned, so if the first element has a higher index - which is possible in Bash - you'll get the empty string; try 'a[1]='hi'; echo "$a"'.
(By contrast, zsh, ever the renegade, indeed doesreturn the first element, irrespective of its index).

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

You may choose to eschew this feature due to its obscurity, but it works predictably and, pragmatically speaking, you'll rarely, if ever, need to access indices otherthan 0of array variable ${BASH_SOURCE[@]}.

您可以选择避开这一功能,因为它默默无闻,但它的工作原理可以预见和务实地讲,你会很少,如果有的话,需要访问索引其他0数组变量${BASH_SOURCE[@]}

回答by Huw Walters

These scripts may help illustrate. The outer script calls the middle script, which calls the inner script:

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

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

However, if we change the script calls to sourcestatements:

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

##代码## ##代码## ##代码## ##代码##