bash and fish scripts are not compatible, but I would like to have a file that defines some some environment variables to be initialized by both bash and fish.

My proposed solution is defining a ~/.env file that would contain the list of environment variables like so:


I could then just source it in bash and make a script that converts it to fish format and sources that in fish.

I was thinking that there may be a better solution than this, so I'm asking for better way of sharing environment variables between bash fish.

Note: I'm using OS X.

Here is an example .env file that I would like both fish and bash to handle using ridiculous-fish's syntax (assume ~/bin and ~/bin2 are empty directories):

setenv _PATH "$PATH"
setenv PATH "$HOME/bin"
setenv PATH "$PATH:$HOME/bin2"
setenv PATH "$PATH:$_PATH"

bash has special syntax for setting environment variables, while fish uses a builtin. I would suggest writing your .env file like so:

setenv VAR1 val1
setenv VAR2 val2

and then defining setenv appropriately in the respective shells. In bash (e.g. .bashrc):

function setenv() { export "$1=$2"; }
. ~/.env

In fish (e.g. config.fish):

function setenv; set -gx $argv; end
source ~/.env

Note that PATH will require some special handling, since it's an array in fish but a colon delimited string in bash. If you prefer to write setenv PATH "$HOME/bin:$PATH" in .env, you could write fish's setenv like so:

function setenv
    if [ $argv[1] = PATH ]
        # Replace colons and spaces with newlines
        set -gx PATH (echo $argv[2] | tr ': ' \n)
        set -gx $argv

This will mishandle elements in PATH that contain spaces, colons, or newlines.

The awkwardness in PATH is due to mixing up colon-delimited strings with true arrays. The preferred way to append to PATH in fish is simply set PATH $PATH ~/bin.

  • 1
    Will the PATH fix for fish work with paths with: spaces? newlines? other things to look out for? – Tyilo Dec 28 '14 at 23:28
  • [ is a builtin in both bash and fish, so PATH should not need to be set correctly to use [. The setenv sample should work with all characters in PATH except for colons and newlines. – ridiculous_fish Dec 30 '14 at 0:35
  • Replacing tr with /usr/bin/tr I and using the .env file provided in my question, I get a lot of errors when starting fish. I don't think the PATH handling is correct. – Tyilo Dec 30 '14 at 0:39
  • Oh, right, fish will space-separate it inside quotes. I'll update the comment. – ridiculous_fish Dec 31 '14 at 7:50
  • Yay it works now. I don't think any other shell (except fish?) allows paths with colons in PATH anyway. – Tyilo Dec 31 '14 at 16:38

There is (now?) an easier way, per @Zanchey's answer here

Fish Shell: How to set multiple environment variables from a file using export

The digest though is:


echo -e "foo=3\nfoobar=4" > .env; export (cat .env); env | grep foo


echo -e "foo=3\nfoobar=4" > .env; export $(cat .env | xargs); env | grep foo

with the difference being $ and the use of xargs

  • Much more convinient and without any special syntax. Thank you – Panayotis Jun 27 '18 at 20:18

Most Unix systems use PAM. The pam_env module reads a file very much like your .env.

On Linux, pam_env reads a system file /etc/environment and a user file ~/.pam_environment. On OS X (and other *BSD, which likewise use OpenPAM), it appears that pam_env only reads the system file, so you can't set variables per user this way, only for all users.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.