Paymahn Moghadasian
Paymahn Moghadasian

Reputation: 10349

Modifying PATH with fish shell

I'm currently playing around with the fish shell and I'm having some trouble wrapping my head around how the PATH variable is set. For what it's worth, I'm also using oh-my-fish.

If I echo my current path I get:

➜ fish echo $PATH
/usr/local/bin /usr/bin /bin /usr/sbin /sbin /usr/local/bin /opt/X11/bin /usr/texbin /Users/myname/.opam/system/bin

Looking at ~/.config/fish/config.fish I see the following line

set PATH /usr/local/bin $PATH /Users/myname/.opam/system/bin

My question is (and this phrasing will probably reflect my lack of knowledge on the subject): prior to config.fish being processed, where is the PATH variable set? ie: where do all of the paths between /usr/local/bin and /Users/myname/.opam/system/bin come from?

Upvotes: 173

Views: 182274

Answers (8)

Maximilian
Maximilian

Reputation: 8530

Current answer

As of fish 3.2.0, released in March 2021, the canonical approach is:

fish_add_path /opt/mycoolthing/bin

This works both one-off interactively, and in config.fish — it won't produce duplicates in the config.fish case.


Previous answer for fish < 3.2.0:

The recommended commands for modifying PATH from fish's maintainers are:

  1. If you want to run the command once:

    set -Ua fish_user_paths /path
    
  2. If you want to add a command to a startup script, this is idempotent:

     contains /path $fish_user_paths; or set -Ua fish_user_paths /path
    

Upvotes: 208

Tarik Waleed
Tarik Waleed

Reputation: 147

The way that worked with me :

in your ~/.config/fish/config.fish add the following line:

set -gx PATH /path/to/dir1 /path/to/dir2 $PATH This will append those directories to your $PATH Environment variable.

Upvotes: 7

Jorj
Jorj

Reputation: 2701

You may use a script like the one below to ease adding or removing paths:

#!/usr/bin/env fish

#remove PHP72
for argv in /usr/local/opt/[email protected]/bin /usr/local/opt/[email protected]/sbin;
    while contains $argv $fish_user_paths
        set -l index (contains -i $argv $fish_user_paths)
        set –erase –universal fish_user_paths[$index]
    end
end

#add PHP74
for argv in /usr/local/opt/[email protected]/bin /usr/local/opt/[email protected]/sbin;
    if contains $argv $fish_user_paths
        echo "Path already contains $argv"
    else
fish_add_path $argv
    end
end

echo $fish_user_paths | tr " " "\n" | nl

brew services stop [email protected]
brew services start [email protected]

Copied from https://www.tai.ro/2021/10/22/how-to-switch-path-in-fish-shell-with-example-script/

Upvotes: 0

Janusz Skonieczny
Janusz Skonieczny

Reputation: 19030

Above solutions do not work well with python virtual environment. The path to virtual environment will not be the first one in the list.

In order to set path once and do not override it every time you start python virtual environment

You need to change the path conditionally in ~/.config/fish/config.fish, like this:

contains /home/$USER/.pyenv/bin $PATH; or set -x PATH "/home/$USER/.pyenv/bin" $PATH
contains /home/$USER/.local/bin $PATH; or set -x PATH "/home/$USER/.local/bin" $PAT
contains /home/$USER/.asdf/bin $PATH; or source ~/.asdf/asdf.fish

This will ensure that you have new paths in $PATH but wnen you spawn new shell for virtual environment you'll will not add these paths again.

Unfortunately paths set with set -Ua fish_user_paths would endup in the beginning of the $PATH, pushing your virtual environment path away from the first place.

Upvotes: 0

jorjun
jorjun

Reputation: 134

1. Enumerate user paths:

echo $fish_user_paths | tr " " "\n" | nl

2. Append a new bin path, permanently:

set -ga fish_user_paths my_appended_path

3. Remove 7th bin search path by index: (see #1):

set —eg fish_user_paths[7]

Upvotes: 7

Ishmael MIRZAEE
Ishmael MIRZAEE

Reputation: 1210

In order to set variables for shell config file, I did as follows:

The main command to set any user specific variable is

set -Ua fish_user_paths /path/to/bin/directory/

set -Ux fish_user_paths /usr/local/bin Run touch ~/.config/fish/config.fish, unless it exists.

  1. RUST: set -Ua fish_user_paths $HOME/.cargo/bin

  2. JAVA: set -Ua fish_user_paths /path/to/java/bin

  3. Node & nvm: make sure you have installed nvm properly then

    omf install nvm

    set -gx NVM_DIR /path/to/nvm

  4. Go: set -Ua fish_user_paths /path/to/go/bin/

  5. Scala: set -Ua fish_user_paths /path/to/scala/bin/

  6. Groovy: set -Ua fish_user_paths /path/to/groovy/bin/

  7. Maven: set -Ua fish_user_paths /path/to/mvn/bin/

  8. Gradle: set -Ua fish_user_paths /path/to/groovy/bin/

Finally, refresh your terminal.

PS in some operating system (eg OpenSuse), drop a.

The result after configuration

Upvotes: 3

Kasper
Kasper

Reputation: 13622

As stated in the official fish tutorial, you can modify the $fish_user_paths universal variable.

Run the following once from the command-line:

set -U fish_user_paths /usr/local/bin $fish_user_paths

This will prepend /usr/local/bin permanently to your path, and will affect the current session and all future instances too because the -U argument will make the variable universal.

From the fish documentation:

... (Note: you should NOT add this line to config.fish. If you do, the variable will get longer each time you run fish!)

fish_user_paths, a list of directories that are prepended to PATH. This can be a universal variable.

Upvotes: 247

Zanchey
Zanchey

Reputation: 2040

Like all shells, fish inherits its PATH from the environment it is started in. How this is set for login shells differs between operating systems - on Linux, for example, /etc/login.defs controls the initial PATH set for all login shells. I don't know how this is set on OS X.

Next, like bash or csh, the initialisation files for the shell may alter the path. For fish on OS X, there is code in share/fish/config.fish to load paths from the standard OS X path configuration files /etc/paths and /etc/paths.d/*. There is alternative code to set a useful path on Solaris.

There is also code to pick up paths from the universal variable $fish_user_paths, which is the right way to add something to your PATH and have it reflected across all shells.

Upvotes: 12

Related Questions