22

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?

  • grep -R /usr/lib/x86_64-linux-gnu/libfm ~/.config/fish /usr/share/fish ?? – glenn jackman Jul 2 '14 at 16:10
  • $grep -R /usr/lib/x86_64-linux-gnu/libfm ~/.config/fish /usr/share/fish /home/superuser/.config/fish/fish_history:grep -R /usr/lib/x86_64-linux-gnu/libfm ~/.config/fish /usr/share/fish – tomekK Jul 3 '14 at 6:16
37

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
| improve this answer | |
  • 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.. – Pär Nils Amsen Jan 30 '18 at 10:12
  • 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. – Elijah Lynn Oct 10 '18 at 16:13
11

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
| improve this answer | |
  • 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. – clozach Aug 29 '17 at 19:51
  • This is great, just added to my local! – Elijah Lynn Nov 29 '17 at 0:07
3

This should erase paths 6 through the last path:

set -e PATH[6..-1]

The -e flag is erase. See help set.

| improve this answer | |
  • this will only work for the current session – Daniel Nov 4 '19 at 12:36
0

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

| improve this answer | |

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.