re-use '~/.profile` for Fish?

35

18

(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

Posted 2012-07-10T02:41:17.243

Reputation: 5 059

Answers

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

Posted 2012-07-10T02:41:17.243

Reputation: 5 059

3can you explain what this does? – max pleaner – 2017-01-13T18:00:27.973

@maxpleaner AFAICT it looks through .profile for export statements and executes them as fish sets. It's kinda hacky, but clever. – Jared Smith – 2018-10-09T13:40:24.960

29

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 +x /usr/local/bin/fishlogin
    
  3. Add it to /etc/shells

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

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

Noé Rubinstein

Posted 2012-07-10T02:41:17.243

Reputation: 390

So elegant! Should be the accepted answer IMO – yonix – 2017-03-22T08:11:51.427

3Just in case anyone is wondering, the mac equivalent of usermod -s /usr/local/bin/fishlogin $USER is chsh -s /usr/local/fishlogin $USER – gloriphobia – 2017-05-10T09:52:09.393

2If you get chsh: /usr/local/bin/fishlogin: non-standard shell need to add it to /etc/shells – Ben Marten – 2017-06-03T22:06:37.770

1To fully imitate launching fish directly, fish "$@" should be replaced with exec -l fish "$@". exec replaces the bash process with fish, while -l causes that argv[0] for fish is -fish, which signals that this is a login shell. – jhrmnn – 2018-02-12T10:28:08.677

Usually no big deal, but this seems to have the drawback that whenever a subshell is implicitly created, an unnecessary bash instance will also always be launched first. (Note: ~/.profile is only relevant for login shells.) Still upvoted, though, for its good trade-off between simplicity and hackyness. (I'd personally still rather just tweak my shell config scripts a bit, as I've long given up having complicated ones, in favor of custom shell-independent methods.) – Sz. – 2018-09-14T19:49:48.210

1@Sz. Well, nope. Fish does not support subshells in the first place. And even if it did, it would not do so by executing your login shell, so no Bash would be spawned then. – Noé Rubinstein – 2018-10-03T11:12:19.573

Note that fish reorders and modifies the entries in $PATH, which you might find confusing. See here.

– Albert – 2019-01-17T09:08:13.020

14

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

fenv source ~/.profile

jgillich

Posted 2012-07-10T02:41:17.243

Reputation: 800

6This should be the accepted solution. You could elaborate (install omf) – Jules Randolph – 2018-04-18T20:36:43.480

@JulesRandolph installation of Oh My Fish is not required. The foreign_env fish plugin can be installed alone, it doesn't have dependencies. – Dominykas Mostauskis – 2019-10-20T16:59:06.233

5

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

Posted 2012-07-10T02:41:17.243

Reputation: 151

this is awesome thank you – ggnoredo – 2019-05-10T07:57:45.550

If you're going to use this method, make sure it isn't too slow. I personally started to notice that my shell startup delay was annoyingly long, and tracked it down to bass. – mk12 – 2019-09-05T21:01:29.967

@mk12 probably it isn't bass' fault, it is your .profile that has too much going on. – rsalmei – 2019-09-06T17:21:20.967

@rsalmei All I had in there was environment variable and alias definitions, with a few if statements. It causes no noticeable delay in bash. So I think it is bass's fault. On the other hand, I'm much happier with the fenv plugin. It's written in shell rather than Python and seems much faster for me.

– mk12 – 2019-09-07T18:05:51.387

Yeah @mk12, it seems to be nice, but also way more limited, as it only captures environment variables. bass on the other hand interprets any bash shell script, and make them run in fish. It certainly will have a bit more overhead, but totally negligible in my experience, but your mileage may vary. – rsalmei – 2019-09-11T19:41:36.273

4

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

Eswar Rajesh Pinapala

Posted 2012-07-10T02:41:17.243

Reputation: 171

Worked for me too! Running MacOSX. – Alexar – 2015-12-06T03:33:11.150

Won't work with more complex .profile files that use syntax not available in fish. – erb – 2016-10-06T10:12:15.320

1@erb I agree with you, I added the caveat in the answer. – Eswar Rajesh Pinapala – 2016-10-06T22:54:20.993

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

yegorius

Posted 2012-07-10T02:41:17.243

Reputation: 29

Probably don't even need to install dash - just sh will do (which is probably dash) – Wayne Werner – 2019-05-21T06:10:14.207

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

Posted 2012-07-10T02:41:17.243

Reputation: 84 656

I don't want to fully execute .profile. I just want to get all exports from there. One easy way would be to egrep "^export" which would be good enough already for me. Another, more correct solution would be this. Also, I e.g. could run this import_bash_settings.py script which probably does something similar. So, there are obviously many ways to do this. With my question here, I was wondering how others have solved this.

– Albert – 2012-07-11T14:18:34.567

1

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

kzh

Posted 2012-07-10T02:41:17.243

Reputation: 3 213

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

Posted 2012-07-10T02:41:17.243

Reputation: 11