【问题标题】:${BASH_SOURCE[0]} equivalent in zsh?${BASH_SOURCE[0]} 在 zsh 中的等价物?
【发布时间】:2012-03-28 04:33:40
【问题描述】:

标题应该说明一切。我正在 zsh 中寻找与 ${BASH_SOURCE[0]} 等效的对象。

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

我在我的.zshrc 中真正在做什么(那是行不通的):

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

源失败($0 是 zsh),echo 输出一个空行。

编辑: 显然,要使$0 工作,我需要设置FUNCTION_ARGZERO 选项。有什么方法可以测试这是否在脚本中设置? (以便我可以临时设置它) 除非您设置nofunction_argzero,否则它显然是开启的,并且它在我的shell 中是开启的。 $0 仍然一无所获。 (我认为 b/c 我不在函数中。)

【问题讨论】:

    标签: shell zsh


    【解决方案1】:

    ${(%):-%x} 是最接近的zsh,相当于bash 的$BASH_SOURCE(和ksh 的${.sh.file}) - 不是 @ 987654328@.

    感谢郑慧在his answer中提供关键指针和背景信息。

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

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

    我发现与$BASH_SOURCE 的唯一区别在于以下晦涩的场景 - 这甚至可能是一个错误(在 zsh 5.0.5 中观察到):在一个函数内嵌套在另一个函数内脚本,${(%):-%x} not 在调用嵌套函数时返回封闭的脚本路径(再次)稍后,在已经被获取(返回没有或'zsh')。


    背景信息${(%):-%x}:

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

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

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

    【讨论】:

    • 是否有文档说明除了 -%x 之外还有哪些其他选项可用?
    【解决方案2】:

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

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

    以最近开始的为准。如果没有,则相当于参数$0。”(来自man zshmisc)

    【讨论】:

    • 太棒了 - 这应该适用于 OP,但请注意真正的 $BASH_SOURCE 等价物是 %x,而不是 %N,因为它指的是封闭的 文件即使在 functions 内部调用 - 换句话说:使用 ${(%):-%x}
    • 嘿,阅读文档,我不明白为什么我们需要这里的:-,以及为什么${(%)%N} 不能正常工作(注意:我知道它不是工作)
    • 是否有文档说明除了 -%N 之外还有哪些其他选项可用?
    • 注意:如果你的zshrc文件是符号链接,可以使用readlink解析为绝对路径:readlink -f ${(%):-%N}
    • 如果您想要一种更简洁的方法来查找包含源代码的目录的绝对路径,这将处理:${${(%):-%x}:A:h}
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

      • 我仍然不确定这是否正确。创建这两个文件:foo 包含 source ./foo2 和 foo2 包含 echo $0。现在运行./foo,您将得到./foo 的输出,它不是源脚本的名称。将$0 替换为${BASH_SOURCE[0]},用bash 重新运行,您将得到./foo2。
      • @Thanatos 我得到了./foo2(zsh 4.3.10;这可能在某些时候发生了变化,但自 4.0 以来没有)。和你的说明相比,我在foo的顶部添加了#!/bin/zsh,用于在zsh下运行脚本。你确定你在zsh下运行foo?
      • 只是为了澄清和强调...在 zsh(可能还有其他 shell)中,$0 的值是源脚本而不是调用者脚本。这不是它在 Bash 中的工作方式。所以 zsh 中的 $0 与 Bash 中的 ${BASH_SOURCE[0]} 相同。
      • @Gilles: .zshrc 是来源 - 因为所有初始化/配置文件都是出于它们的目的。除此之外,zsh通常总是报告$0中的脚本路径,无论脚本是否被获取。显然,一个例外是初始化/配置文件,其中zsh 的行为类似于bash 和ksh,将$0 设置为shell 的 路径(由于采购)。 (因此,如果有的话,$0 不 在这种情况下反映 script 路径这一事实是.zshrc 是的另一个指标> 来源。)真正的 zsh 等价于 $BASH_SOURCE 是 ${(%):-%x}。
      • @toxalot: $0 in zsh 在大多数但不是全部情况下相当于$BASH_SOURCE;例外情况是:(a) 在 initialization/profile 文件 中(例如,~/.zshrc)$0 莫名其妙地报告 shell 的 路径,以及 (b) 在 function 它报告函数的 名称。同样,真正的等价物是${(%):-%x}。
      【解决方案5】:

      如果您正在符号链接到 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 )"
      

      (我从here得到循环脚本。)

      【讨论】:

      • 是否有文档说明除了 -%N 之外还有哪些其他选项可用?
      【解决方案6】:

      也许您正在寻找$_?

      # foo.sh
      source foo2.sh
      

      和

      # foo2.sh
      echo $_
      

      产量

      # ./foo.sh
      foo2.sh
      

      【讨论】:

      • 获得最佳效果:${BASH_SOURCE:-$_}
      • 最好的做法是解释为什么您提供的答案有效,或者在这种情况下,答案是,包括对此的基本解释特征。 (见鬼,即使复制粘贴手册页的一小部分也不是一个坏主意!)
      • $_ 在 bash 中不适用于 script1.sh 源 script2.sh 然后回显 $_ 的情况。它将返回 script1.sh,即 $0(主脚本),而 ${BASH_SOURCE[0]} 返回 script2.sh(调用 echo $_ 的下标)。所以 $_ 基本上就像 $0 AFAICS。
      • 对于其他想知道 WTF $_ 的人来说:“当你启动它(例如 $_ = /bin/bash)或脚本时,_ 变量设置为你的 shell 的绝对文件名如果在调用 shell 时传入参数列表,则执行。之后,它总是扩展为最后执行的命令的值,或键入的参数“(来自linuxshellaccount.blogspot.com/2008/04/…)
      猜你喜欢
      • 1970-01-01
      • 2014-01-17
      • 2016-11-23
      • 2023-04-06
      • 1970-01-01
      • 1970-01-01
      • 2013-06-18
      • 2019-12-04
      • 1970-01-01
      相关资源
      最近更新 更多