如何从 zsh shell 获取包含 BASH_SOURCE 的 bash 脚本?

如何从 zsh shell 获取包含 BASH_SOURCE 的 bash 脚本?

我有一个 bash 脚本,如下所示:

...
SOME_VARIABLE=$(readlink -f $(dirname ${BASH_SOURCE[0]}))
export SOME_VARIABLE
...

我需要从 zsh shell 获取它,因为我需要拥有它定义的所有环境变量。

问题是由于 BASH_SOURCE 我收到此错误消息:

dirname: missing operand
Try 'dirname --help' for more information.
readlink: missing operand
Try 'readlink --help' for more information.
Invalid location:

约束条件: 我无法修改脚本。

问题:我可以从 zsh 获取包含 BASH_SOURCE 的 bash 脚本吗?

答案1

不要这样做. /path/to/that/script.bash,而是:

BASH_SOURCE=/path/to/that/script.bash emulate ksh -c '. "$BASH_SOURCE"'

emulate ksh -c '...'在模拟中运行代码ksh(例如,数组索引从 0 开始,就像在 bash 中一样),并确保其中定义的所有函数都继承该模拟模式。

$BASH_SOURCEinbash指的是正在获取的文件,因此我们使用脚本的路径预先填充该变量。

zsh该代码的等价物是bash

export SOME_VARIABLE=$0:h:P

:h给出就像 csh 中的那样(相当于dirname),以及:P相当于 GNU readlink -f)。

无论如何,那

SOME_VARIABLE=$(readlink -f $(目录名 ${BASH_SOURCE[0]}))

bash您需要的代码不正确:

SOME_VARIABLE=$(
  readlink -f -- "$(dirname -- "$BASH_SOURCE")"
)

请注意,即使这样,如果 dirname$BASH_SOURCE之前或之后以换行符结尾,它也不会工作readlink -f

答案2

凉爽的;我有一个类似的问题 - 经过再三考虑后,我通过其他方式解决了这个问题 - 但这个问题实际上很有趣。而且解决方案非常优雅(我认为是这样)。

主要/真正的问题(AFAIU)是:

我需要从 zsh shell 获取它,因为我需要拥有它定义的所有环境变量。

, 在哪里是 Bash 脚本。

脚本使用的事实BASH_SOURCE实际上是次要的;剧本巴什,期间。我们可能认为它是一个“黑匣子”,我们想要做的就是找出其中定义(或修改)了哪些变量。

  • 脚本必须有源猛击。

话虽这么说,我们要做的是(从 Bash 解释器内部)

  1. 缓冲初始状态环境的,
  2. 来源剧本,
  3. 缓冲之后的状态环境的,
  4. 差异缓冲区。

您/我们应该打印出新的/修改的变量。

拟议的解决方案-- 上述步骤 -- 看起来像:

% bash -c 'buf1=$(env|sort) && source bashrc && buf2=$(env|sort) && diff <(echo "$buf1") <(echo "$buf2")'

,其中bashrc是假定脚本的名称。

请注意,这实际上适用于任何shell(zsh、csh、ksh 等),只要安装了 Bash 并且版本与脚本兼容(最有可能发生,但值得注意)。

作为一个例子,我这里有以下脚本——我称之为bashrc

#!/bin/bash
HERE=$(cd `dirname $BASH_SOURCE`; pwd)
PATH="${HERE}/bin:$PATH"
export HERE
export PATH

,它定义一个新变量 --$HERE并修改现有变量 -- $PATH。我把这个脚本放在我的/tmp目录中。上面的命令给了我:

6a7
> HERE=/tmp
15c16
< PATH=/Users/chbrandt/bin/links:/Users/chbrandt/bin/links:/Users/chbrandt/bin/links:/opt/miniconda3/bin:/opt/miniconda3/condabin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
---
> PATH=/tmp/bin:/Users/chbrandt/bin/links:/Users/chbrandt/bin/links:/Users/chbrandt/bin/links:/opt/miniconda3/bin:/opt/miniconda3/condabin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

很甜蜜,不是吗? ...现在你做一些后处理(例如在你的 zsh 中)来处理符号和其他任何东西,就是这样;)

相关内容