50

(I'm talking about the shell Fish, esp. Fish's Fish.)

For Bash/ZSH, I had ~/.profile with some exports, aliases and other stuff.

I don't want to have a separate config for environment variables for Fish, I want to re-use my ~/.profile. How?

In The FAQ, it is stated that I can at least import those via /usr/local/share/fish/tools/import_bash_settings.py, however I don't really like running that for each Fish-instance.

Albert
  • 6,889
  • 11
  • 41
  • 53

11 Answers11

46

You can use bash to parse /etc/profile and ~/.profile, and then start fish.

  1. Create /usr/local/bin/fishlogin with contents

     #!/bin/bash -l
     exec -l fish "$@"
    
  2. Make it executable

     sudo chmod a+rx /usr/local/bin/fishlogin
    
  3. Check that it works by running fishlogin and checking that you end up in a Fish shell. Press Control+D to exit the Fish shell.

  4. Add it to /etc/shells

     echo /usr/local/bin/fishlogin | sudo tee -a /etc/shells
    
  5. Set it as your default shell.

    Under Linux:

     sudo usermod -s /usr/local/bin/fishlogin $USER
    

    Under macOS:

     chsh -s /usr/local/bin/fishlogin $USER
    
37

For a much cleaner solution, you can use the foreign env plugin:

fenv source ~/.profile
jgillich
  • 1,070
15

My current solution (see here for a maybe more recent version):

egrep "^export " ~/.profile | while read e
    set var (echo $e | sed -E "s/^export ([A-Z_]+)=(.*)\$/\1/")
    set value (echo $e | sed -E "s/^export ([A-Z_]+)=(.*)\$/\2/")

    # remove surrounding quotes if existing
    set value (echo $value | sed -E "s/^\"(.*)\"\$/\1/")

    if test $var = "PATH"
        # replace ":" by spaces. this is how PATH looks for Fish
        set value (echo $value | sed -E "s/:/ /g")

        # use eval because we need to expand the value
        eval set -xg $var $value

        continue
    end

    # evaluate variables. we can use eval because we most likely just used "$var"
    set value (eval echo $value)

    set -xg $var $value
end
Albert
  • 6,889
  • 11
  • 41
  • 53
11

You can use bass, a plugin to execute bash commands in fish.

  1. Install bass.

    $ git clone https://github.com/edc/bass.git
    $ cd bass
    $ make install
    
  2. And then, just put this in your config.fish:

    bass source ~/.profile
    
rsalmei
  • 211
6

I tried sourcing .profile on fish startup and it worked like a charm for me.

just do :

echo 'source ~/.profile;clear;' >  ~/.config/fish/config.fish

Restart terminal or iterm2, test an alias from .profile to test.

Note : Won't work with more complex .profile files that use syntax not available in fish - credit @erb

3

Install dash and add this line to your config.fish:

env -i HOME=$HOME dash -l -c 'export -p' | sed -e "/PATH/s/'//g;/PATH/s/:/ /g;s/=/ /;s/^export/set -x/" | source
1

You can't. fish's syntax is too different from Bourne shell (/bin/sh) syntax. This is the same reason you can't use .profile with other non-Bourne-derived shells, such as csh and tcsh.

Spiff
  • 110,156
1

If your distribution uses PAM, you could set your environment variables in your ~/.pam_environment file.

kzh
  • 4,473
1

You can start Fish from Bash. If you do that, Fish will inherit all environment variables (export FOO=bar) from Bash. At this point, Bash will have already read your .profile (or the like).

bash-3.2$ export TEST="test"
bash-3.2$ fish
cmey@MBP ~> echo $TEST
test
cmey
  • 11
0

I managed to solve this by adding the following to my ~/.bashrc file:

if [ $SHLVL -lt 2 ]; then 
    fish; 
    exit;
fi

This way one does not have to type exit twice when exiting the fish subshell. Bash subshells inside the fish subshell are not affected.

ben
  • 1
0

You can try code below. It works for me.

if status is-login
    if not set -q __sourced_profile
        set -x __sourced_profile 1
        exec bash -c "\
            test -e /etc/profile && source /etc/profile
            test -e $HOME/.bash_profile && source $HOME/.bash_profile
            exec fish --login
        "
    end
# put your configs below

#

set -e __sourced_profile

end