fish、zsh、bash可以导入同一个配置文件吗?

Can fish, zsh and bash import the same configuration file?

我最近一直在尝试从 bash 切换到 zshfish

我有一些 alisa 和 PATH 设置,但我不想手动将它们复制到 zshrcconfig.fish.

我尝试将它们写在一个文件中并使用 source ~/.myshrc 来使用它们。

alisa statement可以正常取货。但是当在 fish shell 中采购 PATH 时,我得到了一个错误:

In fish, please use {$JAVA_HOME}. export
CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib

我知道 fish 和 bash 语法不兼容。

那么是否有一个通用的语法允许我修改 myshrc 中的 PATH 然后所有三个 shell 都可以使用它?

myshrc 文件如下:

# alias 
alias apts="apt search"
alias sf="aptitude search -F '%c %p %d %D %I'"
alias apti="sudo aptitude install"
alias aptup="sudo aptitude update"
alias aptgr="sudo aptitude upgrade"
alias aptpu="sudo aptitude purge"

# transset xterm
transset -t -a 0.95 >> /dev/null 2>&1


# set npm path
export PATH=~/.npm-global/bin:$PATH

# set java path
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 
export JRE_HOME=${java_home}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH

# set android path
export ANDROID_HOME="/home/moly/Launcher/AndroidSDK/"
export PATH="${PATH}:${ANDROID_HOME}tools/:${ANDROID_HOME}platform-tools/"

在尝试过渡到新的 shell(如 fish)时使用现有配置的一种 hacky 方法是简单地用 fish 结束你的 ~/.bashrc,就像这样:

# alias 
alias apts="apt search"
alias sf="aptitude search -F '%c %p %d %D %I'"
alias apti="sudo aptitude install"
alias aptup="sudo aptitude update"
alias aptgr="sudo aptitude upgrade"
alias aptpu="sudo aptitude purge"

# transset xterm
transset -t -a 0.95 >> /dev/null 2>&1


# set npm path
export PATH=~/.npm-global/bin:$PATH

# set java path
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 
export JRE_HOME=${java_home}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH

# set android path
export ANDROID_HOME="/home/moly/Launcher/AndroidSDK/"
export PATH="${PATH}:${ANDROID_HOME}tools/:${ANDROID_HOME}platform-tools/"

# start fish
exec fish

我认为这不是一个很好的解决方案,但这是我所知道的唯一一个使 fish 继承您的 bash 环境而不需要 rewriting/translating 您的 bashrc。虽然这可能是一种不好的做法并且可能会导致其他类型的问题,但从短期来看,如果您只想使用别名在已知区域尝试 fish 并且 PATH 无需花费,这可能就是您所需要的写配置文件的时间也许是白费的。

我没有使用zsh的经验,不知道它是否可以像那样同样继承bash环境,但如果可以也不会感到惊讶。

简答:

如果您采用“鱼的方式”做事,您可以将启动配置精简到一行...

解释:

首先,只是为了传递一些随机知识(我最初是在 Stack Overflow 上的相关回答中学到的),代码的编写方式与 运行 中的方式相同两种不同的语言被称为polyglot。它通常被认为是某种“拼图”,而不是实际的实现。真的不建议将其作为您问题的解决方案。

接下来,我的一般建议是尽可能采用鱼类做事方式。当然,出于兼容性原因,有时您需要退回到 POSIX,但是 fish 语法(恕我直言)更清晰。

我特别喜欢,在 fish 下,我的配置文件几乎是空的。 不需要 fish 下有许多你在 bash 启动时拥有的项目。

让我们分解一下启动配置中的四种类型的项目:

  • 别名
  • $PATH 变化
  • 其他导出变量
  • 其他命令

别名

我建议不要在您的 fish 启动文件中放置别名。只是没有必要。相反,在命令行定义别名 once 并使用 -s(保存)选项。你的情况:

alias -s apts="apt search"
alias -s sf="aptitude search -F '%c %p %d %D %I'"
alias -s apti="sudo aptitude install"
alias -s aptup="sudo aptitude update"
alias -s aptgr="sudo aptitude upgrade"
alias -s aptpu="sudo aptitude purge"

此时您的别名将在所有 fish 实例中“永久”定义,其优点是它们是“延迟加载”(仅在您第一次 运行 时才加载到内存中)而不是一直在加载中。


$PATH 修改

同样,fish 提供了一个方便的助手,您可以使用它添加到您的路径一次并使其在所有实例中生效(当前 运行ning 和未来)。

fish_add_path "~/.npm-global/bin" "/usr/lib/jvm/java-17-openjdk-amd64/bin" "~/Launcher/AndroidSDK/tools" "~/Launcher/AndroidSDK/platform-tools"

这会将这些路径添加到内置鱼 universal variable$fish_user_paths 中,后者会自动添加到系统路径中。请注意,在您的 bash rc 中,您已 附加 Android SDK 路径,但这 可能 没有必要。通常,您会希望在系统路径之前添加用户路径。


其他导出变量

这部分有点争议,因为 fish 通用变量在导出到其他进程时可能会产生意想不到的副作用。

一方面,一位鱼类维护者 (@faho) 在 中提到:

In general, what you want is to just put the set -gx into ~/.config/fish/config.fish. That's fish's configuration file.

Fish also has "universal" variables, which are stored persistently, but they interact awkwardly with exporting so I wouldn't recommend it.

我有其他人(见 this answer 上的评论)也建议不要使用鱼。

另一方面,this answer 上有 196 票赞成票似乎表明出于此目的人们喜欢通用。这并不是说大多数人都是正确的——我见过一些非常糟糕的答案,但得到了很多赞成票。

不过,我个人喜欢使用它们来简化我的配置文件。

如果你这样选择,你可以:

set -Ux JAVA_HOME "/usr/lib/jvm/java-17-openjdk-amd64"
set -Ux JRE_HOME "$JAVA_HOME/jre"
set -Ux --path CLASSPATH ".:$JAVA_HOME/lib:$JRE_HOME/lib"
set -Ux ANDROID_HOME "/home/moly/Launcher/AndroidSDK/"

同样,由于这些是通用变量,它们只需要在命令行上设置一次。然后,您可以从您的 fish 启动中删除这些语句。

了解 universal/global 变量阴影:

首先,如果设置了 global 变量(例如,由您启动 fish 的父 bash 进程设置),那么它将覆盖通用变量同名

例如(病态的例子,但在现实世界中很容易发生,特别是如果你没有意识到这种可能性):

# Start in Fish
-> set -Ux JAVA_HOME "/usr/lib/jvm/java-17-openjdk-amd64"
-> set --show JAVA_HOME
$JAVA_HOME: set in universal scope, exported, with 1 elements
$JAVA_HOME[1]: |/usr/lib/jvm/java-17-openjdk-amd64|
-> bash
-> export JAVA_HOME="~/.local/share/jvm/java-17-openjdk-amd64"
-> fish
-> set --show JAVA_HOME
$JAVA_HOME: set in global scope, exported, with 1 elements
$JAVA_HOME[1]: |~/.local/lib/jvm/java-17-openjdk-amd64|
$JAVA_HOME: set in universal scope, exported, with 1 elements
$JAVA_HOME[1]: |/usr/lib/jvm/java-17-openjdk-amd64|

在那个特定的钓鱼会话中,通用变量将被在 bash 中导出的全局变量覆盖。

请参见 中的 this Github issue,其中 很多 证明了现实世界中潜在的问题。

同样,考虑到这一点,我个人认为导出通用变量的好处大于风险,但我想确保提出这两种观点。

其他命令

如果到目前为止你一直在跟进(而且还没有睡着——我知道我过度解释了......),那么你会意识到(可能)只有一个命令 必须留在你的鱼创业公司:

transset -t -a 0.95 >> /dev/null 2>&1

即便如此,我也有一个建议。 Fish 自动获取 ~/.config/fish/conf.d 中的任何 .fish 文件。我喜欢保持我的配置“模块化”,这样我就可以一目了然地知道在启动时加载了什么。

我只想创建:

~/.config/fish/conf.d/xterm.fish:

transset -t -a 0.95 >> /dev/null 2>&1

那时,你和我一样 运行ning -- 根本没有 fish.config! (好吧,除了较新的 fish 版本令人恼火之外,如果它不存在,则会自动创建一个完全不必要的空版本......)