${BASH_SOURCE[0]} 等值于 zsh?

${BASH_SOURCE[0]} equivalent in zsh?

提问人:Thanatos 提问时间:3/28/2012 最后编辑:Thanatos 更新时间:8/12/2023 访问量:32403

问:

标题应该说明一切。我正在寻找相当于 zsh 的。${BASH_SOURCE[0]}

注意:我一直在互联网上找到“等同于”,但这似乎是错误的:似乎是执行命令的名称。(这是,这是有道理的。在我的脚本 () 中回显 $0 给出了 ,这与 is 不同。事实上,似乎可以在 中工作,除了内部文件。$0${BASH_SOURCE[0]}$0argv[0].zshrczsh$0${BASH_SOURCE[0]}${BASH_SOURCE[0]}zsh.zshrc

我在我的 .zshrc 中真正在做什么(不起作用):

echo ${BASH_SOURCE[0]}
source `dirname $0`/common-shell-rc.sh

源失败 ( is ) 并输出空行。$0zshecho

编辑:显然,要使 0 美元起作用,我需要选项FUNCTION_ARGZERO选项集。有什么方法可以测试它是否在脚本中设置?(这样我就可以临时设置了)除非您设置,否则它显然是打开的,并且它在我的外壳中打开。仍然一无所获.(我认为 b/c 我不在一个函数中。nofunction_argzero$0

壳牌 ZSH

评论


答:

11赞 Gilles 'SO- stop being evil' 3/29/2012 #1

$0是正确的。在源脚本中,这是脚本的名称,因为它被传递给 或内置(因此,如果设置了该选项,则可能需要进行查找以查找脚本的实际位置)。.sourcepath_dirs$path

.zshrc没有来源,这解释了为什么不设置为 。无论如何,您都知道文件名和位置:它是 .$0.zshrc${ZDOTDIR-~}/.zshrc

评论

0赞 Thanatos 3/29/2012
我仍然不确定这是否正确。创建以下两个文件:containing 和 containing .现在运行 ,你将获得 的输出,这不是源脚本的名称。替换为 ,用 bash 重新运行,您将获得 .foosource ./foo2foo2echo $0./foo./foo$0${BASH_SOURCE[0]}./foo2
0赞 Gilles 'SO- stop being evil' 3/29/2012
@Thanatos我得到了(zsh 4.3.10;这可能在某个时候发生了变化,但自 4.0 以来没有)。与您的说明相比,我在 的顶部添加了 ,以在 zsh 下运行脚本。你确定你在 zsh 下运行吗?./foo2#!/bin/zshfoofoo
3赞 toxalot 3/20/2014
只是为了澄清和强调......在 zsh(可能还有其他 shell)中,的值是源脚本,而不是调用方脚本。这不是它在 Bash 中的工作方式。所以在 zsh 中和在 Bash 中是一样的。$0$0${BASH_SOURCE[0]}
1赞 mklement0 2/5/2015
@Gilles:来源 - 因为所有初始化/配置文件都是按其目的进行的。除此之外,通常 ALWAYS 在 中报告脚本路径,无论脚本是否被引用。显然,一个例外是初始化/配置文件,其中 zsh 的行为类似于 bash 和 ksh,设置为 shell 的路径(由于来源)。(因此,如果有的话,在这种情况下不反映脚本路径的事实是另一个正在获取的指标。真正的 zsh 等价物是 。.zshrczsh$0$0$0.zshrc$BASH_SOURCE${(%):-%x}
2赞 mklement0 2/5/2015
@toxalot:in 等同于大多数情况,但不是所有情况;例外情况是:(a) 在初始化/配置文件中(例如,) 莫名其妙地报告 shell 的路径,以及 (b) 在函数内部报告函数的名称。同样,真正的等价物是 。$0zsh$BASH_SOURCE~/.zshrc$0${(%):-%x}
2赞 Coderer 8/27/2013 #2

也许你正在寻找 ?$_

# foo.sh
source foo2.sh

# foo2.sh
echo $_

收益 率

# ./foo.sh
foo2.sh

评论

1赞 mpapis 10/23/2013
为获得最佳效果:${BASH_SOURCE:-$_}
1赞 ELLIOTTCABLE 12/26/2014
最佳做法是解释您提供的答案为什么有效,或者,在这种情况下,答案是<X feature>,包括对该功能的基本解释。(见鬼,即使复制粘贴一小段手册页也绝不是一个坏主意!
0赞 David Faure 1/9/2015
$_ 在 bash 中不起作用,因为 script1.sh 源 script2.sh 然后会回显 $_。它将返回 script1.sh,即 $0(主脚本),而 ${BASH_SOURCE[0]} 返回 script2.sh(调用 echo $_ 的下标)。所以 $_ 基本上就像 0 美元的 AFAICS 一样。
1赞 ACK_stoverflow 5/20/2021
对于其他任何想知道 WTF 的人:“当你启动它时,_ 变量被设置为你的 shell 的绝对文件名(例如 $_ = /bin/bash),或者如果它在调用 shell 时在参数列表中传递,则被设置为正在执行的脚本。之后,它总是扩展到最后一个执行的命令的值,或键入的参数“(来自 linuxshellaccount.blogspot.com/2008/04/...$_)
75赞 Hui Zheng 4/24/2014 #3

${BASH_SOURCE[0]}zsh 中的等价物是 , NOT(正如 OP 所说,后者在 .zshrc 中失败了)${(%):-%N}$0

这里表示对值的提示扩展,表示“脚本的名称、源文件、 或 zsh 当前正在执行的 shell 函数,%%N

以最近开始的为准。如果没有,则等效于参数 $0。(从man zshmisc)

评论

23赞 mklement0 2/5/2015
太好了 - 这应该适用于 OP,但请注意,真正的等价物是 ,而不是 ,因为它指的是封闭文件,即使在函数内部调用时也是如此 - 换句话说:使用$BASH_SOURCE%x%N${(%):-%x}
1赞 PierreBdR 7/29/2015
嘿,阅读文档,我不明白为什么我们在这里需要 in,以及为什么不能以同样的方式工作(注意:我知道它不起作用):-${(%)%N}
0赞 Martin 7/8/2016
是否有文档,除了 -%N 形式之外,还有哪些其他选项可用?
1赞 Bryce Guinta 11/29/2016
注意:如果你的 zshrc 文件是符号链接,你可以使用 解析为绝对路径:readlinkreadlink -f ${(%):-%N}
5赞 basicdays 4/13/2021
如果您想要一种更简洁的方法来查找包含源代码的目录的绝对路径,这将处理:${${(%):-%x}:A:h}
10赞 Francis Potter 10/22/2014 #4

如果要符号链接到 dotfiles 目录中的 .zshrc,并且想要引用该目录中的其他文件,请尝试以下操作:

SOURCE=${(%):-%N}
while [ -h "$SOURCE" ]; do
  DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
  SOURCE="$(readlink "$SOURCE")"
  [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
done
DOTFILES_DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"

(我从这里得到了循环脚本。

评论

1赞 Martin 7/8/2016
是否有文档,除了 -%N 形式之外,还有哪些其他选项可用?
67赞 mklement0 2/5/2015 #5

${(%):-%x} 是最接近 的等价物 (和 's) - 不是zshbash$BASH_SOURCEksh${.sh.file}$0

感谢 Hui Zheng 在他的回答中提供了关键的指针和背景信息。

它返回封闭脚本的(可能是相对的)路径,

  • 无论脚本是否被获取
    • 具体来说,它还可以在初始化/配置文件中工作,例如(不像 ,它莫名其妙地返回 shell 的路径)。~/.zshrc$0
  • 无论是否从脚本中定义的函数内部调用(与 不同,它返回函数内部的函数名称)。$0

我发现与 $BASH_SOURCE 的唯一区别是在以下晦涩难懂的场景中 - 这甚至可能是一个错误(在 zsh 5.0.5 中观察到):在嵌套在源脚本中另一个函数中的函数中,${(%):-%x} 在稍后调用该嵌套函数时,${(%):-%x} 不会返回封闭的脚本路径,在获取后(返回 nothing 或 'zsh')。


背景资料${(%):-%x}

  • (%):-代替参数(变量)中的变量名称,扩展 () 使转义序列可用,这些转义序列通常用于在提示字符串中表示环境信息,例如在变量中用于确定显示为主要交互式提示的字符串。${...}PS1

    • %是参数扩展标志的一个实例,所有这些标志都列在标题下。man zshexpnParameter Expansion Flags
  • %x是可以在提示字符串中使用的转义序列之一,其功能如上所述;还有更多,例如表示当前目录。%d

    • man zshmisc列出标题 下的所有可用序列。SIMPLE PROMPT ESCAPES

评论

1赞 Martin 7/8/2016
是否有文档,除了 -%x 形式之外,还有哪些其他选项可用?
26赞 dols3m 2/19/2019 #6

如果你想让你的脚本同时兼容 bash 和 zsh,你可以使用 .生成的值将从定义时和未定义时获取。${BASH_SOURCE[0]:-${(%):-%x}}BASH_SOURCE[0]${(%):-%x}}BASH_SOURCE[0]

1赞 Samuel Neff 8/12/2023 #7

把它们放在一起,在 bash 和 zsh 中都有效:

SCRIPT_FILE_REL_PATH="${BASH_SOURCE[0]}"
if [[ "$SCRIPT_FILE_REL_PATH" == "" ]]; then
  SCRIPT_FILE_REL_PATH="${(%):-%N}"
fi
SCRIPT_FILE_PATH="`realpath $SCRIPT_FILE_REL_PATH`"
SCRIPT_DIR="`dirname $SCRIPT_FILE_PATH`"