如何使用 zsh 或 bash 使 shell 自检测

我有一个关于如何判断用户正在使用哪个 shell 的问题。假设一个脚本,如果用户正在使用 zsh,那么将 PATH 放到他的 .zshrc中,如果使用 bash 则应该放入。巴希尔。并相应地设置 RVMRC。

#!/usr/bin/env bash
export PATH='/usr/local/bin:$PATH' >> ~/.zshrc
source ~/.zshrc

我试过以下方法,但没有效果:

if [[ $0 == "bash" ]]; then
export PATH='/usr/local/bin:$PATH' >> ~/.bashrc
elif [[ $0 == "zsh" ]]; then
export PATH='/usr/local/bin:$PATH' >> ~/.zshrc
fi


# ... more commands ...


if [[ $0 == "bash" ]]; then
[[ -s '/Users/`whoami`/.rvm/scripts/rvm' ]] && source '/Users/`whoami`/.rvm/scripts/rvm' >> ~/.bashrc
source ~/.bashrc
elif [[ $0 == "zsh" ]]; then
[[ -s '/Users/`whoami`/.rvm/scripts/rvm' ]] && source '/Users/`whoami`/.rvm/scripts/rvm' >> ~/.zshrc
source ~/.zshrc
fi
61210 次浏览

如果 shell 是 Zsh,则定义变量 $ZSH_VERSION

if [ -n "$ZSH_VERSION" ]; then
# assume Zsh
elif [ -n "$BASH_VERSION" ]; then
# assume Bash
else
# assume something else
fi

但是,这些变量只能告诉您正在使用哪个 shell 来运行上面的代码。因此,您必须在用户的 shell 中对这个片段进行 source

作为一种替代方法,你可以使用 $SHELL环境变量(它应该包含用户首选 shell 的绝对路径)并根据该变量的值猜测 shell:

case $SHELL in
*/zsh)
# assume Zsh
;;
*/bash)
# assume Bash
;;
*)
# assume something else
esac

当然,当 /bin/sh是到 /bin/bash的符号链接时,上述操作将失败。

如果您想依赖于 $SHELL,那么实际执行一些代码会更安全:

if [ -n "$($SHELL -c 'echo $ZSH_VERSION')" ]; then
# assume Zsh
elif [ -n "$($SHELL -c 'echo $BASH_VERSION')" ]; then
# assume Bash
else
# assume something else
fi

无论使用哪个 shell 来运行脚本,都可以从脚本运行最后一个建议。

一句警告: 你似乎问的问题,你想问的问题,和你应该问的问题是三件不同的事情。

“用户正在使用哪个 shell”是模棱两可的。您的尝试看起来像是试图确定哪个 shell 正在执行您的脚本。无论你放在脚本的 #!行中的是什么,它都是一样的,除非你想让你的用户编辑那个脚本,所以这对你没有用。

我认为,您想问的是用户最喜欢的 shell 是什么。这不能完全可靠地确定,但是您可以覆盖大多数情况。检查 ABc0环境变量。如果它包含 fishzshbashkshtcsh,用户最喜欢的 shell 可能就是这个 shell。然而,对于你的问题来说,这是个错误的问题。

.bashrc.zshrc.cshrc等文件都是 shell 初始化文件。它们不是定义环境变量的正确位置。定义的环境变量只能在用户启动 shell 的终端中使用,而不能在从 GUI 启动的程序中使用。该定义还将覆盖用户可能在子会话中完成的任何自定义。

定义环境变量的正确位置是在会话启动文件中。这主要与用户选择 shell 无关。不幸的是,没有单一的地方来定义环境变量。在许多系统上,~/.profile都可以工作,但这并不是普遍适用的。请参阅 https://unix.stackexchange.com/questions/4621/correctly-setting-environment和我链接到那里的其他帖子以获得更长的讨论。

另一种选择,可能不适用于所有的 shell。

for x in $(ps -p $$)
do
ans=$x
done
echo $ans

我自己也遇到了类似的问题,最终决定:

_shell="$(ps -p $$ --no-headers -o comm=)"
if [[ $_shell == "zsh" ]]; then
read -q -s "?Do it?: "
fi
elif [[ $_shell == "bash" || $_shell == "sh" ]]; then
read -n 1 -s -p "Do it [y/n] "
fi

只要做 echo $0 如果是 就是 -zsh如果是 < em > bash 就是 -bash

编辑: 有时返回 -zsh,有时返回 zsh,bash 也是如此。

以下是基于吉尔斯先前的一个回答,我是如何做到这一点的:

if [ -n "$ZSH_VERSION" ]; then
SHELL_PROFILE="$HOME/.zprofile"
else
SHELL_PROFILE="$HOME/.bash_profile"
fi
echo "export VAR1=whatever" >> $SHELL_PROFILE
echo "INFO: Refreshing your shell profile: $SHELL_PROFILE"
if [ -n "$ZSH_VERSION" ]; then
exec zsh --login
else
source $SHELL_PROFILE
fi

你可以试试

 echo $SHELL

其他答案在 set -u中失败

  if [ ! -z ${ZSH_VERSION+x} ]; then
echo "this is zsh"
echo ${(%):-%x}
elif [ ! -z ${BASH_VERSION+x} ]; then
echo "this is bash"
echo $BASH_SOURCE
else
echo "not recognized"
fi