How to remove a path from $PATH variable in fish?

14,444

Solution 1

The 'fish' way of setting the $PATH variable is to actually use set --universal fish_user_paths $fish_user_paths /new/path/here. Then $fish_user_paths is actually prepended to the $PATH variable when a new session starts. The $PATH documentation doesn't currently tell you how to delete it though.

In fish every variable is actually a list (array), and you can conveniently access each item directly by using an index/indice. echo $fish_user_paths will print out a space delimited version of every item in the list, make the spaces newline with the translate function echo $fish_user_paths | tr " " "\n" and then put line numbers on it with the number lines function, echo $fish_user_paths | tr " " "\n" | nl. Then delete it with set --erase --universal fish_user_paths[5]. You must use --universal or it will not work in any new sessions.

If someone has the time, please submit a PR to the repo with this example. I opened an issue here.

tldr;

  1. echo $fish_user_paths | tr " " "\n" | nl // get the number of the one you want to delete, e.g. the 5th one
  2. set --erase --universal fish_user_paths[5] // erase the 5th path universally so it persists in new sessions

Solution 2

As Elijah says, best practice is to modify the fish_user_paths rather than the global PATH. To avoid ever having to Google this again…

  1. Create a couple of functions that only modify fish_user_paths
  2. Make both functions autoloading

To add to user paths:

function addpaths
    contains -- $argv $fish_user_paths
       or set -U fish_user_paths $fish_user_paths $argv
    echo "Updated PATH: $PATH"
end

To remove a user path if it exists (partial credit to this):

function removepath
    if set -l index (contains -i $argv[1] $PATH)
        set --erase --universal fish_user_paths[$index]
        echo "Updated PATH: $PATH"
    else
        echo "$argv[1] not found in PATH: $PATH"
    end
end

And of course, to make them autoloading:

funcsave addpaths; funcsave removepath

Example Usage:

> addpaths /etc /usr/libexec
Modifying PATH: /usr/local/bin /usr/bin /bin /usr/sbin /sbin
Updated PATH: /etc /usr/libexec /usr/local/bin /usr/bin /bin /usr/sbin /sbin
> removepath /usr/libexec
Modifying PATH: /etc /usr/libexec /usr/local/bin /usr/bin /bin /usr/sbin /sbin
Updated PATH: /etc /usr/local/bin /usr/bin /bin /usr/sbin /sbin

Solution 3

This should erase paths 6 through the last path:

set -e PATH[6..-1]

The -e flag is erase. See help set.

Solution 4

Reset fish_user_paths withtout the path you don't want anymore:

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

More info: https://fishshell.com/docs/current/tutorial.html#tut_path

Share:
14,444

Related videos on Youtube

tomekK
Author by

tomekK

Updated on September 18, 2022

Comments

  • tomekK
    tomekK 3 months

    I am using fish as my shell in Debian and recently (after some upgrade) whenever I try to use command completion I have:

    set: No such file or directory
    set: Could not add component /usr/lib/x86_64-linux-gnu/libfm to PATH.
    set: No such file or directory
    

    Running this:

    echo $PATH 
    

    Gives me this:

    /usr/lib/x86_64-linux-gnu/libfm /usr/local/bin /usr/bin /bin /usr/local/games /usr/games
    

    In my system there is no /usr/lib/x86_64-linux-gnu/libfm, so I understand why fish is complaining, but I cannot find how to remove this path from my $PATH variable.

    Does anyone know how can I do this?

    • glenn jackman
      glenn jackman over 8 years
      grep -R /usr/lib/x86_64-linux-gnu/libfm ~/.config/fish /usr/share/fish ??
  • clozach
    clozach over 5 years
    Note: I've just discovered that this approach won't remove a path added through some other mechanism; Some dot-file cleanup may be in order if you find a path coming back each time you open a new terminal session.
  • Elijah Lynn
    Elijah Lynn about 5 years
    This is great, just added to my local!
  • Pär Nils Amsen
    Pär Nils Amsen almost 5 years
    Why is this so arcane? Shouldn't this be a build in feature and added to the documentation so that people doesn't have to Google and end up here? Oh well..
  • Elijah Lynn
    Elijah Lynn about 4 years
    I think if we take @clozach's answer here superuser.com/a/1212305/30982, which is the addpaths() and removepath() function, and open a PR then that would be the first step to getting it added. Most of the maintainers are pretty good to work with, one seems grumpy to me, but overall I think we would have a good chance. So that is our next step.
  • Daniel
    Daniel about 3 years
    this will only work for the current session
  • theprogrammer
    theprogrammer over 1 year
    This is not working for me. It just prints the back to me, thats all.
  • theprogrammer
    theprogrammer over 1 year
    echo $fish_user_paths doesn't return anything, but echo $PATH returns some stuff.
  • Elijah Lynn
    Elijah Lynn over 1 year
    What does echo $SHELL return? It should return /usr/bin/fish or something like that. My suspicion is that it is a different shell. If it is fish, then what is fish --version?
  • demisx
    demisx over 1 year
    This set --erase --universal fish_user_paths[4] doesn't work for me in v3.3.1 for some reson. No errors, but the path is not being deleted from the list.
  • m0j0
    m0j0 over 1 year
    A better solution, added in a more recent version of fish, is to use the fish_add_path command. fishshell.com/docs/current/cmds/fish_add_path.html
  • ivan_pozdeev
    ivan_pozdeev 9 months
    Using spaces as delimiters will break if a path has a space in it. The only 100% safe delimiter is \0.