How to remove a path from $PATH variable in fish?
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?
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;
-
echo $fish_user_paths | tr " " "\n" | nl
// get the number of the one you want to delete, e.g. the 5th one -
set --erase --universal fish_user_paths[5]
// erase the 5th path universally so it persists in new sessions
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…
- Create a couple of functions that only modify
fish_user_paths
- 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
This should erase paths 6 through the last path:
set -e PATH[6..-1]
The -e flag is erase. See help set
.