
语境:
- M1 MacBook
- macOS Ventura 13.5.2
- zsh 作为默认 shell
- 通过 homebrew 安装 GNU coreutils
/opt/homebrew/opt/coreutils/libexec/gnubin
添加到~/.bashrc
、~/.bash_profile
和中的路径~/.bash_login
我有 bash 脚本
- 从...开始
#!/usr/bin/env bash
date
使用适用于 GNU date(/opt/homebrew/opt/coreutils/libexec/gnubin
) 但不能用于 macOS date(/bin/date
)的参数进行调用date
从 zsh 交互调用时失败,因为调用了 错误- 这不是猜测,我检查过
which date
等等echo $PATH
- 如果我首先以交互方式运行 bash,然后从 bash 而不是 zsh 调用脚本,它就会起作用
- 这不是猜测,我检查过
这看起来像是当 zsh 启动我的脚本时路径更改~/.bash*
未被加载。
为了证实这一点,我echo ".bashrc"
向每个脚本中添加了类似的行~/.bash*
,但运行脚本时没有出现任何消息。
在 zsh 中,which bash
给出/opt/homebrew/bin/bash
,并bash --version
以GNU bash, version 5.2.15(1)-release (aarch64-apple-darwin22.1.0)
如何让 bash 加载其脚本配置?
答案1
请阅读手册的以下部分:6.2 Bash 启动文件。它描述了根据调用的方式获取哪些文件bash
。解释脚本时bash
,它不会自动获取任何内容。您的选择:
以交互和/或登录 shell运行
bash
。会有副作用,所以我不推荐这样做。在您想要影响的每个脚本中明确获取所需的文件。
创建一个可执行包装器,它获取一些文件,然后
exec
将其转换为bash
。一个简单粗暴的例子是:#!/bin/sh . /path/to/file exec /path/to/bash "$@"
想要使用包装器的脚本必须在其 shebang 中指定它(而不是
bash
)。请注意,源由file
解释包装器的 shell 解释(/bin/sh
在示例中),并且它不能直接更改bash
稍后启动的配置;为此,bash
它只能更改继承的内容,例如PATH
在环境中。通过选择
bash
脚本的 shebang 中的包装器,您可以决定该脚本是由 vanillabash
还是“配置”的脚本来解释。使用
BASH_ENV
:
例如,当以非交互方式启动 Bash 以运行 shell 脚本时,它会
BASH_ENV
在环境中查找变量,如果变量出现则扩展其值,并使用扩展的值作为要读取和执行的文件的名称。Bash 的行为就像执行了以下命令一样:if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
但变量的值
PATH
不用于搜索文件名。
看起来最后一种方法就是你想要的。使你的 Zsh* 环境包含BASH_ENV
并且变量的值是 Bash 某个配置文件的完整路径。配置文件可能是
- 一些标准文件(例如你的
.bashrc
), - 或包含一个或多个标准文件的自定义文件,
- 或者只改变专用的自定义文件
PATH
, - 或者执行任何您想要的自定义文件。
笔记:
诸如此类的文件
.bashrc
可能包含 Bash 解释脚本时不打算执行的代码(因为在这种情况下通常不会执行这些代码),因此需要专门的自定义文件仅有的改变PATH
似乎是个好主意。BASH_ENV
环境中的脚本将影响由其解释的任何脚本bash
和任何bash -c
调用。脚本调用脚本可能会导致自定义文件的效果累积。请考虑将其放置unset BASH_ENV
在自定义文件中。混合方法是可行的。例如这个包装器:
#!/bin/sh BASH_ENV=/path/to/custom_file exec /path/to/bash "$@"
将使
bash
(不sh
)源化custom_file
。这可以被认为是对之前引入的包装器的改进。使用此包装器(或其他包装器)时,您不需要BASH_ENV
在 Zsh 环境中。更多:如果您希望能够轻松运行 vanilla,bash
那么您不需要想BASH_ENV
在你的 Zsh 环境中。
* 应该有一种方法可以将变量添加到您的桌面或其他任何地方的环境中(即不仅仅是 Zsh),但我不了解 macOS,因此无法详细指导您。