【问题标题】:Can fish, zsh and bash import the same configuration file?fish、zsh和bash可以导入同一个配置文件吗?
【发布时间】:2022-01-20 08:50:31
【问题描述】:

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

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

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

alisa statement 可以正常获取。但是在鱼壳中采购PATH 时出现错误:

在fish中,请使用{$JAVA_HOME}。出口
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/"

【问题讨论】:

  • 不存在类似“配置文件”的东西。 “.bashrc”可以包含任何复杂性的任何代码,它是一个程序。如果你想在另一个解释器中运行为 Bash 编写的程序,你必须交叉编译它。如果您想将自己限制为像属性文件这样的简单键值列表,则必须为 Bash 和 Fish 编写两个解析器来读取文件,以便设置别名和环境变量。
  • 请注意,fish 语法与 bash 和 zsh 使用的 POSIX shell 语法不兼容。所以,不,除了极其微不足道的 .bashrc 之外,您不能将其内容用作 config.fish。此外,bash 和 fish alias 命令不做同样的事情;尽管它们足够相似,以至于您通常可以忽略差异。

标签: linux bash fish


【解决方案1】:

在尝试转换到 fish 等新 shell 时,使用现有配置的一种简单方法是简单地以 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 环境而不重写/翻译你的bashrc。虽然这可能是不好的做法,并且可能会导致其他类型的问题,但在短期内,如果您只想在已知领域使用别名和 PATH 尝试 fish 而无需花费时间编写配置,这可能就是您所需要的文件也许一无所获。

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

【讨论】:

  • 这会禁用 Bash。我认为他想要保留他的.bashrc 的原因是,即使他在大多数情况下使用 Fish,他仍然想执行 Bash。顺便说一句:你可能想在最后做exec fish 以释放未使用的 Bash 的内存。
  • 是的,它不是最理想的。我认为这对他们有用的原因是当我自己转换到fish 时遇到了同样的问题:我不想承诺编写一个全新的配置(我的~/.bashrc 很大)知道我是否会留在fish。使用这个 hacky 的短期解决方案帮助了我。我仍然可以通过在我的fish shell(它将在那个终端窗口中启动bash)运行bash 来使用bash,或者只使用bash -c "commands"。用bash 编写的脚本仍然可以开箱即用。感谢exec fish 的提示,我已编辑。
【解决方案2】:

简答:

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

解释:

首先,只是为了传递一些随机知识(我最初是在 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"

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


$PATH修改

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

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) 在 this answer 中提到:

一般来说,您只需将 set -gx 放入~/.config/fish/config.fish。那是fish的配置文件。

Fish 也有“通用”变量,它们被持久存储,但它们与导出的交互很尴尬,所以我不推荐它。

我也有其他人(请参阅this answer 上的 cmets)也曾与 fish 进行过广泛合作。

另一方面,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 启动中删除这些语句。

了解通用/全局变量阴影:

首先,如果设置了一个 全局 变量(例如,由您启动 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 of 许多,它们展示了现实世界中潜在的问题。

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

其他命令

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

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

那时,你就像我一样奔跑——根本没有fish.config! (好吧,除了新的鱼版本令人恼火之外,如果它不存在,它会自动创建一个完全不必要的空...)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-19
    • 2011-12-26
    • 2021-11-03
    • 1970-01-01
    • 1970-01-01
    • 2010-10-30
    相关资源
    最近更新 更多