我有一个 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_SOURCE
inbash
指的是正在获取的文件,因此我们使用脚本的路径预先填充该变量。
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 解释器内部)
- 缓冲初始状态环境的,
- 来源剧本,
- 缓冲之后的状态环境的,
- 差异缓冲区。
您/我们应该打印出新的/修改的变量。
拟议的解决方案-- 上述步骤 -- 看起来像:
% 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 中)来处理符号和其他任何东西,就是这样;)