6

I've recently been trying to switch from bash to zsh, or fish.

I have some alisa and PATH settings, but I don't want to manually copy them to zshrc or config.fish.

I tried writing them in a single file and using source ~/.myshrc to use them.

The alisa statement can be sourced normally. But when sourcing PATH in fish shell I got an error:

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

I know that fish and bash syntax are incompatible.

So is there a general syntax that allows me to modify the PATH in myshrc and then all three shells can use it?

myshrc file like this:

# 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/"

molychan
  • 121
  • 7
  • 1
    Does this help? https://stackoverflow.com/a/29387647/775806 – n. m. could be an AI Jan 20 '22 at 09:23
  • Something like a "configuration file" does not exist. A ".bashrc" can contain any code of any complexity, it is a program. If you want to run a program written for Bash in another interpreter, you have to cross-compile it. If you want to restrict yourself to a simple key-value list like a properties file, you have to write two parsers for Bash and Fish to read the file in order to set aliases and environment variables. – ceving Jan 20 '22 at 11:47
  • Note that fish syntax is incompatible with POSIX shell syntax used by bash and zsh. So, no, other than an extremely trivial .bashrc you can't use its contents as your config.fish. Also, the bash and fish `alias` command don't do the same thing; although they are similar enough that you can often ignore the differences. – Kurtis Rader Jan 20 '22 at 15:50
  • In the shell `xonsh`, you can load `.bashrc` by running: `source-bash ~/.bashrc` . – Flimm May 09 '22 at 14:09

2 Answers2

3

One hacky way to use your existing configuration while trying to transition to a new shell like fish is simply to end your ~/.bashrc with fish, like so:

# 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

I don't think this is a very good solution, but this is the only one I know of to make fish inherit your bash environment without rewriting/translating your bashrc. While this is probably bad practice and could cause other sorts of issues, on the short term this could be what you need if you just want to try out fish in known territory with your aliases and PATH without spending time writing a configuration file perhaps for nothing.

I have no experience with zsh and don't know if it can equally inherit the bash environment like that, but wouldn't be surprised if it can.

Matf
  • 46
  • 2
  • 1
    This disables Bash. I think the reason why he wants to keep his `.bashrc` is, that he still wants to execute a Bash even if he uses Fish in most cases. Btw: You probably want to do `exec fish` at the end to free the memory of the unused Bash. – ceving Jan 20 '22 at 13:18
  • Yes it's suboptimal. The reason I thought it would be useful to them is I went through the same kind of issues when I transitionned to `fish` myself: I didn't want to commit to writing a whole new config (my `~/.bashrc` was huge) before knowing whether I would stay on `fish` at all. Using this hacky short-term solution helped me. I could still use `bash` by running `bash` inside my `fish` shell (which would start `bash` in that terminal window), or just using `bash -c "commands"`. Scripts written in `bash` would still work out of the box. Thanks for the tip on `exec fish`, I edited. – Matf Jan 20 '22 at 16:31
3

Short answer:

If you embrace the "fish way" of doing things, you can get your startup config down to just one line ...

Explanation:

First off, just to pass along some random knowledge (that I originally learned here in a related answer on Stack Overflow), code that is written in such a way that it runs the same way in two different languages is known as a polyglot. It's typically considered a "puzzle" of sorts, rather than a practical implementation. It's really not advised as a solution to your question.

Next up, my general recommendation is to embrace the fish way of doing things as much as possible. Sure, there are times you'll need to drop back to POSIX for compatibility reasons, but fish syntax is (IMHO) much cleaner.

I especially like that, under fish, my config files are almost empty. It's just not necessary under fish to have many of the items that you have in your bash startup.

Let's break down the four types of items you have in your startup config:

  • Aliases
  • $PATH changes
  • Other exported variables
  • Other Command(s)

Aliases

I recommend against putting aliases in your fish startup files. It's just not necessary. Instead, define the alias once at the commandline and use the -s (save) option. In your case:

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"

Your aliases will be "permanently" defined at that point in all fish instances, with the advantage that they are "lazy loaded" (only loaded into memory when you run them the first time) rather than being loaded at all times.


$PATH modifications

Likewise, fish provides a handy helper with which you can add to your path once and have it take effect in all instances (both currently running and future).

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

This prepends those paths to the built-in fish universal variable$fish_user_paths which is automatically prepended to the system path. Note that, in your bash rc, you have appended the Android SDK paths, but that's probably not necessary. Typically, you will want to prepend user paths ahead of the system path.


Other exported variables

This part is a little contentious, because fish universal variables can have unintended side-effects when exported to other processes.

On one hand, one of the fish maintainers (@faho) mentions in this answer that:

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.

I've had others (see comments on this answer) who have worked extensively with fish advise against it as well.

On the other hand, 196 upvotes on this answer seem to indicate that folks like universals for this purpose. That's not to say that the majority is correct -- I've seen some really bad answers with a lot of upvotes.

However, I personally like using them to simplify my config files.

If you so choose, you can:

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/"

Again, as these are universal variables, they only need to be set once on the commandline. You can then remove those statements from your fish startup.

Understanding universal/global variable shadowing:

Primarily, if a global variable is set (for instance, by the parent bash process from which you launch fish), then it will override a universal variable of the same name.

For instance (pathologic example, but can easily occur in the real world, especially if you aren't aware of the potential):

# 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|

In that particular fish session, the Universal variable will be shadowed by the global one that was exported in bash.

See this Github issue of many that demonstrate the real world potential for problems.

Again, with that in mind, I personally believe the benefits of exported universal variables outweigh the risks, but I wanted to be sure to present both viewpoints.

Other commands

If you've followed along so far (and haven't fallen asleep -- I known I over-explain ...), then you'll realize that there's (potentially) only the one command that must remain in your fish startup:

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

Even then, I have a suggestion. Fish automatically sources any .fish file in ~/.config/fish/conf.d. I like to keep my config "modularized", so that I can tell at-a-glance what is being loaded at startup.

I would just create:

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

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

At that point, you are running like I do -- no fish.config at all! (Well, other than the fact that the newer fish versions irritatingly, automatically create a completely unnecessary empty one if it doesn't exist ...)

NotTheDr01ds
  • 15,620
  • 5
  • 44
  • 70