New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to set $PATH persistently? #527

Closed
dag opened this Issue Jan 18, 2013 · 40 comments

Comments

Projects
None yet
@dag
Contributor

dag commented Jan 18, 2013

I try set -U PATH ~/.cabal/bin $PATH which sets it in the shell I type it in, but not any new shells I launch and it's gone if I restart the first shell as well.

Using git HEAD on Fedora 18.

@siteshwar

This comment has been minimized.

Show comment
Hide comment
@siteshwar

siteshwar Jan 18, 2013

Member

I think it's because PATH variable is handled specially in Fish. So you can't make it universal etc. I am not aware about the reasons behind it. May be @ridiculousfish or @JanKanis would like to say few words about it.

On Linux I set PATH in ~/.config/fish/config.fish this way :

set -gx PATH /opt/qt/Tools/QtCreator/bin /opt/qt/5.0.0/gcc_64/bin $PATH
Member

siteshwar commented Jan 18, 2013

I think it's because PATH variable is handled specially in Fish. So you can't make it universal etc. I am not aware about the reasons behind it. May be @ridiculousfish or @JanKanis would like to say few words about it.

On Linux I set PATH in ~/.config/fish/config.fish this way :

set -gx PATH /opt/qt/Tools/QtCreator/bin /opt/qt/5.0.0/gcc_64/bin $PATH
@JanKanis

This comment has been minimized.

Show comment
Hide comment
@JanKanis

JanKanis Jan 18, 2013

Member

PATH is normally a global variable, created when fish starts from the environment variable in its environment. If you do set -U PATH <something> that creates a universal variable PATH, but the universal one is shadowed by the global one, so you won't see it. It could work if you do set -eg PATH (delete the global PATH), and you also need to specify the -x flag when you create the universal PATH (set -Ux PATH <something>). But if you execute e.g. a new X terminal, the fish in it again finds a PATH in its environment so it again creates a global PATH. I would recommend you set your path by doing

set PATH <mydir> $PATH

in your config.fish, so it gets executed every time fish starts. That just modifies the existing global PATH.

Member

JanKanis commented Jan 18, 2013

PATH is normally a global variable, created when fish starts from the environment variable in its environment. If you do set -U PATH <something> that creates a universal variable PATH, but the universal one is shadowed by the global one, so you won't see it. It could work if you do set -eg PATH (delete the global PATH), and you also need to specify the -x flag when you create the universal PATH (set -Ux PATH <something>). But if you execute e.g. a new X terminal, the fish in it again finds a PATH in its environment so it again creates a global PATH. I would recommend you set your path by doing

set PATH <mydir> $PATH

in your config.fish, so it gets executed every time fish starts. That just modifies the existing global PATH.

@dag

This comment has been minimized.

Show comment
Hide comment
@dag

dag Jan 18, 2013

Contributor

Ah. I was just wondering if there was a neatly interactive/"live" way to do it.

Contributor

dag commented Jan 18, 2013

Ah. I was just wondering if there was a neatly interactive/"live" way to do it.

@JanKanis

This comment has been minimized.

Show comment
Hide comment
@JanKanis

JanKanis Jan 18, 2013

Member

config.fish lives (by default) in ~/.config/fish/config.fish, and it is
mentioned in the user docs. (But maybe it should be made more clear).
There's also vared for interactive editing of variables (however it only
works on one array element at the time).

On 18 January 2013 21:07, Dag Odenhall notifications@github.com wrote:

Ah. I was just wondering if there was a neatly interactive/"live" way to
do it. config.fish doesn't seem to be documented either so I was
wondering if there even was such a file.


Reply to this email directly or view it on GitHubhttps://github.com/fish-shell/fish-shell/issues/527#issuecomment-12438806.

Member

JanKanis commented Jan 18, 2013

config.fish lives (by default) in ~/.config/fish/config.fish, and it is
mentioned in the user docs. (But maybe it should be made more clear).
There's also vared for interactive editing of variables (however it only
works on one array element at the time).

On 18 January 2013 21:07, Dag Odenhall notifications@github.com wrote:

Ah. I was just wondering if there was a neatly interactive/"live" way to
do it. config.fish doesn't seem to be documented either so I was
wondering if there even was such a file.


Reply to this email directly or view it on GitHubhttps://github.com/fish-shell/fish-shell/issues/527#issuecomment-12438806.

@dag

This comment has been minimized.

Show comment
Hide comment
@dag

dag Jan 18, 2013

Contributor

Yea I was looking in the wrong page. I edited that comment but github sent the mail notification faster.

Contributor

dag commented Jan 18, 2013

Yea I was looking in the wrong page. I edited that comment but github sent the mail notification faster.

@ridiculousfish

This comment has been minimized.

Show comment
Hide comment
@ridiculousfish

ridiculousfish Jan 27, 2013

Member

When fish starts, it modifies PATH to include its bin directory. We really want to be able to tell users that they can permanently modify PATH via set -U. So we sort of want a two-level PATH - what fish adds local to the current session, and also what the user specifies, universally across all sessions.

Member

ridiculousfish commented Jan 27, 2013

When fish starts, it modifies PATH to include its bin directory. We really want to be able to tell users that they can permanently modify PATH via set -U. So we sort of want a two-level PATH - what fish adds local to the current session, and also what the user specifies, universally across all sessions.

@ridiculousfish

This comment has been minimized.

Show comment
Hide comment
@ridiculousfish

ridiculousfish Feb 8, 2013

Member

Since setting $PATH is very common, I think it's important to have a story for fish 2.0 that doesn't require the user to edit config.fish. However, simply making it universal is dangerous, because fish is relocatable. If fish is run from /usr/local/bin and also from ~/github/fish/, we want to allow these instances to have distinct PATHs because they have distinct $__fish_bin_dirs. On the other hand, we also want to allow the user to specify one of those bin directories directly.

Here's what I'm thinking:

  1. A variable $fish_user_paths which will be universal. We encourage the user to set it.

  2. A variable $fish_default_paths which will be global (per-process), and that will be set in share/config.fish. It will have at a minimum $__fish_bin_dir, which is fish's bin directory.

  3. $PATH will be global and exported.

  4. There will be an event handler that watches for changes to $fish_user_paths, and updates $PATH like so:

    function __fish_update_path --on-event path-var-changed
    set -gx PATH $fish_user_paths $fish_default_paths
    end

perhaps with some uniqueing to avoid duplicates.

With this design, then:

  1. Setting PATH in config.fish will continue to work, unless something changes $fish_user_paths, which fish will never do on its own.
  2. To add a path to PATH universally, set $fish_user_paths.

I'm not super-happy with this because it requires three variables - it would be nice if there were an approach that only required $PATH. Thoughts?

Member

ridiculousfish commented Feb 8, 2013

Since setting $PATH is very common, I think it's important to have a story for fish 2.0 that doesn't require the user to edit config.fish. However, simply making it universal is dangerous, because fish is relocatable. If fish is run from /usr/local/bin and also from ~/github/fish/, we want to allow these instances to have distinct PATHs because they have distinct $__fish_bin_dirs. On the other hand, we also want to allow the user to specify one of those bin directories directly.

Here's what I'm thinking:

  1. A variable $fish_user_paths which will be universal. We encourage the user to set it.

  2. A variable $fish_default_paths which will be global (per-process), and that will be set in share/config.fish. It will have at a minimum $__fish_bin_dir, which is fish's bin directory.

  3. $PATH will be global and exported.

  4. There will be an event handler that watches for changes to $fish_user_paths, and updates $PATH like so:

    function __fish_update_path --on-event path-var-changed
    set -gx PATH $fish_user_paths $fish_default_paths
    end

perhaps with some uniqueing to avoid duplicates.

With this design, then:

  1. Setting PATH in config.fish will continue to work, unless something changes $fish_user_paths, which fish will never do on its own.
  2. To add a path to PATH universally, set $fish_user_paths.

I'm not super-happy with this because it requires three variables - it would be nice if there were an approach that only required $PATH. Thoughts?

@JanKanis

This comment has been minimized.

Show comment
Hide comment
@JanKanis

JanKanis Feb 9, 2013

Member

Another option that came to mind (though I'm not necessarily advocating for
it, just listing it as another option): Drop the restriction that $PATH can
only contain valid directories, then make it universal. That way a user
could just add all the directories that are possibly needed. Hmm, on second
thought, fish also needs the option of adding its own bindir to PATH,
without clobbering up user settings, so that brings my thinking to a
solution containing a user-settable path and a fish-settable path, i.o.w.
something like you propose.

Another design choice could be to rename $fish_user_paths to the universal
$PATH, and shadow it by a global $PATH, that would save a variable but it's
probably more confusing for users, so not really worth it.

On 8 February 2013 23:17, ridiculousfish notifications@github.com wrote:

Since setting $PATH is very common, I think it's important to have a
story for fish 2.0 that doesn't require the user to edit config.fish.
However, simply making it universal is dangerous, because fish is
relocatable. If fish is run from /usr/local/bin and also from
~/github/fish/, we want to allow these instances to have distinct PATHs
because they have distinct $__fish_bin_dirs. On the other hand, we also
want to allow the user to specify one of those bin directories directly.

Here's what I'm thinking:

  1. A variable $fish_user_paths which will be universal. We encourage
    the user to set it.

  2. A variable $fish_default_paths which will be global (per-process),
    and that will be set in share/config.fish. It will have at a minimum
    $__fish_bin_dir, which is fish's bin directory.

  3. $PATH will be global and exported.
    4.

    There will be an event handler that watches for changes to
    $fish_user_paths, and updates $PATH like so:

    function __fish_update_path --on-event path-var-changed
    set -gx PATH $fish_user_paths $fish_default_paths
    end

perhaps with some uniqueing to avoid duplicates.

With this design, then:

  1. Setting PATH in config.fish will continue to work, unless something
    changes $fish_user_paths, which fish will never do on its own.
  2. To add a path to PATH universally, set $fish_user_paths.

I'm not super-happy with this because it requires three variables - it
would be nice if there were an approach that only required $PATH. Thoughts?


Reply to this email directly or view it on GitHubhttps://github.com/fish-shell/fish-shell/issues/527#issuecomment-13315434..

Member

JanKanis commented Feb 9, 2013

Another option that came to mind (though I'm not necessarily advocating for
it, just listing it as another option): Drop the restriction that $PATH can
only contain valid directories, then make it universal. That way a user
could just add all the directories that are possibly needed. Hmm, on second
thought, fish also needs the option of adding its own bindir to PATH,
without clobbering up user settings, so that brings my thinking to a
solution containing a user-settable path and a fish-settable path, i.o.w.
something like you propose.

Another design choice could be to rename $fish_user_paths to the universal
$PATH, and shadow it by a global $PATH, that would save a variable but it's
probably more confusing for users, so not really worth it.

On 8 February 2013 23:17, ridiculousfish notifications@github.com wrote:

Since setting $PATH is very common, I think it's important to have a
story for fish 2.0 that doesn't require the user to edit config.fish.
However, simply making it universal is dangerous, because fish is
relocatable. If fish is run from /usr/local/bin and also from
~/github/fish/, we want to allow these instances to have distinct PATHs
because they have distinct $__fish_bin_dirs. On the other hand, we also
want to allow the user to specify one of those bin directories directly.

Here's what I'm thinking:

  1. A variable $fish_user_paths which will be universal. We encourage
    the user to set it.

  2. A variable $fish_default_paths which will be global (per-process),
    and that will be set in share/config.fish. It will have at a minimum
    $__fish_bin_dir, which is fish's bin directory.

  3. $PATH will be global and exported.
    4.

    There will be an event handler that watches for changes to
    $fish_user_paths, and updates $PATH like so:

    function __fish_update_path --on-event path-var-changed
    set -gx PATH $fish_user_paths $fish_default_paths
    end

perhaps with some uniqueing to avoid duplicates.

With this design, then:

  1. Setting PATH in config.fish will continue to work, unless something
    changes $fish_user_paths, which fish will never do on its own.
  2. To add a path to PATH universally, set $fish_user_paths.

I'm not super-happy with this because it requires three variables - it
would be nice if there were an approach that only required $PATH. Thoughts?


Reply to this email directly or view it on GitHubhttps://github.com/fish-shell/fish-shell/issues/527#issuecomment-13315434..

@ridiculousfish

This comment has been minimized.

Show comment
Hide comment
@ridiculousfish

ridiculousfish Feb 10, 2013

Member

Having a universal PATH that just accumulates seems harmless. Another thought I had was to try to fix fish so it doesn't depend on PATH to find its own binaries. Then it wouldn't need to modify PATH at all.

Member

ridiculousfish commented Feb 10, 2013

Having a universal PATH that just accumulates seems harmless. Another thought I had was to try to fix fish so it doesn't depend on PATH to find its own binaries. Then it wouldn't need to modify PATH at all.

@ridiculousfish

This comment has been minimized.

Show comment
Hide comment
@ridiculousfish

ridiculousfish Feb 20, 2013

Member

It strikes me that PATH ought never to be a universal variable, because it must be inherited from the environment. That is, if someone sets PATH in bash and then invokes fish, fish ought to respect that, and not overwrite it a universal value.

Here's what I ended up doing:

  1. fish no longer modifies PATH for its own purposes. It knows how to find its own binaries (like fish_indent) without PATH.
  2. Introduced the variable $fish_user_paths. When you modify fish_user_paths, a little function (defined in share/config.fish) runs which performs the same modifications to PATH. fish_user_paths is intended to be universal.

So this is similar to my proposal, except we don't need fish_default_paths. And I think the separation between "here's stuff from the environment" and "here's stuff to add to it" is good. I also like that it required no changes to fish proper, just to config.fish.

So now to append to PATH persistently, append to fish_user_paths, e.g. set -U fish_user_paths ~/bin . I added a note in the documentation too.

To git@github.com:fish-shell/fish-shell.git
2f43584..d3e9183 master -> master

Member

ridiculousfish commented Feb 20, 2013

It strikes me that PATH ought never to be a universal variable, because it must be inherited from the environment. That is, if someone sets PATH in bash and then invokes fish, fish ought to respect that, and not overwrite it a universal value.

Here's what I ended up doing:

  1. fish no longer modifies PATH for its own purposes. It knows how to find its own binaries (like fish_indent) without PATH.
  2. Introduced the variable $fish_user_paths. When you modify fish_user_paths, a little function (defined in share/config.fish) runs which performs the same modifications to PATH. fish_user_paths is intended to be universal.

So this is similar to my proposal, except we don't need fish_default_paths. And I think the separation between "here's stuff from the environment" and "here's stuff to add to it" is good. I also like that it required no changes to fish proper, just to config.fish.

So now to append to PATH persistently, append to fish_user_paths, e.g. set -U fish_user_paths ~/bin . I added a note in the documentation too.

To git@github.com:fish-shell/fish-shell.git
2f43584..d3e9183 master -> master

@saulshanabrook

This comment has been minimized.

Show comment
Hide comment
@saulshanabrook

saulshanabrook Oct 24, 2013

Is there a reason we don't prepend to PATH instead of append? That way use set paths will take precedence, which is my desired use case, at least for Homebrew (/usr/local/bin).

saulshanabrook commented Oct 24, 2013

Is there a reason we don't prepend to PATH instead of append? That way use set paths will take precedence, which is my desired use case, at least for Homebrew (/usr/local/bin).

@ridiculousfish

This comment has been minimized.

Show comment
Hide comment
@ridiculousfish

ridiculousfish Oct 25, 2013

Member

In fish 2.1, we do prepend.

Member

ridiculousfish commented Oct 25, 2013

In fish 2.1, we do prepend.

@xfix

This comment has been minimized.

Show comment
Hide comment
@xfix

xfix Oct 25, 2013

Member

@saulshanabrook: Already fixed with issue #888.

Anyway, I think that universal PATH could be possible, if the PATH would be considered to be just a hint. All directories in PATH would be added to PATH received from environment, unless they already exist, so unless you would really try, you wouldn't break fish.

Member

xfix commented Oct 25, 2013

@saulshanabrook: Already fixed with issue #888.

Anyway, I think that universal PATH could be possible, if the PATH would be considered to be just a hint. All directories in PATH would be added to PATH received from environment, unless they already exist, so unless you would really try, you wouldn't break fish.

@sjatkins

This comment has been minimized.

Show comment
Hide comment
@sjatkins

sjatkins Nov 1, 2013

Not having PATH simply changeable by a normal user action is a major issue and contrary to the beautiful simplicity of fish relative to other shells. Please fix this. It is really a royal pain. I want to set the path and have it work from then on at least in current session if not universally. Do you know how much of a surprise it is that
set -U PATH $PATH my_path
results in an unchanged $PATH? It is ridiculous.

sjatkins commented Nov 1, 2013

Not having PATH simply changeable by a normal user action is a major issue and contrary to the beautiful simplicity of fish relative to other shells. Please fix this. It is really a royal pain. I want to set the path and have it work from then on at least in current session if not universally. Do you know how much of a surprise it is that
set -U PATH $PATH my_path
results in an unchanged $PATH? It is ridiculous.

@zanchey

This comment has been minimized.

Show comment
Hide comment
@zanchey

zanchey Nov 1, 2013

Member

Part of the surprise is due to the fact that you can set universal variables and have global variables override them without warning; perhaps at least in interactive mode we should warn when setting a global or universal variable that has a more specifically-scoped variable with the same name set. This has bitten other variables as well, such as $TERM in #806.

Member

zanchey commented Nov 1, 2013

Part of the surprise is due to the fact that you can set universal variables and have global variables override them without warning; perhaps at least in interactive mode we should warn when setting a global or universal variable that has a more specifically-scoped variable with the same name set. This has bitten other variables as well, such as $TERM in #806.

@terlar

This comment has been minimized.

Show comment
Hide comment
@terlar

terlar Nov 1, 2013

Contributor

EDIT: I just realized this is mentioned above.

If you just want to set the path for the current session, omit the scope and just do set PATH $PATH my_path. This will use whatever scope is used by this session, in this case global.

If you want to persistently add paths you do this through manipulating fish_user_paths. This is a universal variable, set fish_user_paths $fish_user_paths my_path.

Contributor

terlar commented Nov 1, 2013

EDIT: I just realized this is mentioned above.

If you just want to set the path for the current session, omit the scope and just do set PATH $PATH my_path. This will use whatever scope is used by this session, in this case global.

If you want to persistently add paths you do this through manipulating fish_user_paths. This is a universal variable, set fish_user_paths $fish_user_paths my_path.

@daenney

This comment has been minimized.

Show comment
Hide comment
@daenney

daenney Nov 3, 2013

If I set something in $fish_user_paths like /usr/local/bin which is also added through an entry in /etc/paths on OS X /usr/local/bin isn't advanced on $PATH, it stays at the 'back'.

@ridiculousfish stated in fish 2.1 values from $fish_user_paths are prepended to $PATH but it looks like that only happens if the path being added is 'new', if it already exists it stays put.

This is causing slightly whacky behaviour on my system since which pip now returns /usr/local/bin/pip from my homebrew python install but which python return /usr/bin/python, the OS X python install.

The brew plugin in bpinto/oh-my-fish fixes it though but still.

daenney commented Nov 3, 2013

If I set something in $fish_user_paths like /usr/local/bin which is also added through an entry in /etc/paths on OS X /usr/local/bin isn't advanced on $PATH, it stays at the 'back'.

@ridiculousfish stated in fish 2.1 values from $fish_user_paths are prepended to $PATH but it looks like that only happens if the path being added is 'new', if it already exists it stays put.

This is causing slightly whacky behaviour on my system since which pip now returns /usr/local/bin/pip from my homebrew python install but which python return /usr/bin/python, the OS X python install.

The brew plugin in bpinto/oh-my-fish fixes it though but still.

@dideler

This comment has been minimized.

Show comment
Hide comment
@dideler

dideler Jan 14, 2014

Contributor

Correction

The handler for fish_user_paths doesn't set $fish_user_paths as universal.
The correct way to persistently add a path to your $PATH (AFAIK) would be

set --universal fish_user_paths $fish_user_paths ~/path/name

Original post

After some reading and playing around with trying to figure out the "best" way to persistently add a path to your $PATH, I think @terlar's suggestion is best. That is

set fish_user_paths $fish_user_paths my_path
  • Specifying the -U/--universal flag like in set -U fish_user_paths $fish_user_paths my_path seems to be redundant.

  • Leaving out the $fish_user_paths as seen in some places, seems to overwrite your most recent path if you run this command twice with different paths:

    set -U fish_user_paths path1
    set -U fish_user_paths path2
  • Setting the $PATH on every shell instance (e.g. by putting set PATH $PATH my_path in your config.fish) is less efficient than a universal variable that you set once.

Contributor

dideler commented Jan 14, 2014

Correction

The handler for fish_user_paths doesn't set $fish_user_paths as universal.
The correct way to persistently add a path to your $PATH (AFAIK) would be

set --universal fish_user_paths $fish_user_paths ~/path/name

Original post

After some reading and playing around with trying to figure out the "best" way to persistently add a path to your $PATH, I think @terlar's suggestion is best. That is

set fish_user_paths $fish_user_paths my_path
  • Specifying the -U/--universal flag like in set -U fish_user_paths $fish_user_paths my_path seems to be redundant.

  • Leaving out the $fish_user_paths as seen in some places, seems to overwrite your most recent path if you run this command twice with different paths:

    set -U fish_user_paths path1
    set -U fish_user_paths path2
  • Setting the $PATH on every shell instance (e.g. by putting set PATH $PATH my_path in your config.fish) is less efficient than a universal variable that you set once.

@denji

This comment has been minimized.

Show comment
Hide comment
@denji

denji Mar 6, 2014

# NOTE: There is probably a sexier nicer way to do this, but until I figure that out I am manually unsetting here.
# Unsets PATH
set -g -x PATH

# This allows us to use Homebrew versions of things (like git) rather than the pre-installed or XCode installed versions.
# See http://blog.grayghostvisuals.com/git/how-to-keep-git-updated/ for reference.
set -g -x PATH $PATH /usr/local/bin

# Sets necessary PATH defaults
set -g -x PATH $PATH /usr/bin /bin /usr/sbin /sbin

denji commented Mar 6, 2014

# NOTE: There is probably a sexier nicer way to do this, but until I figure that out I am manually unsetting here.
# Unsets PATH
set -g -x PATH

# This allows us to use Homebrew versions of things (like git) rather than the pre-installed or XCode installed versions.
# See http://blog.grayghostvisuals.com/git/how-to-keep-git-updated/ for reference.
set -g -x PATH $PATH /usr/local/bin

# Sets necessary PATH defaults
set -g -x PATH $PATH /usr/bin /bin /usr/sbin /sbin
@yannickoo

This comment has been minimized.

Show comment
Hide comment
@yannickoo

yannickoo Dec 9, 2014

Thank you @dideler, following works fine for adding rvm again:

set --universal fish_user_paths $fish_user_paths ~/.rvm/bin

yannickoo commented Dec 9, 2014

Thank you @dideler, following works fine for adding rvm again:

set --universal fish_user_paths $fish_user_paths ~/.rvm/bin

@Dorian

This comment has been minimized.

Show comment
Hide comment
@Dorian

Dorian Jan 13, 2016

@yannickoo 👍 set --universal fish_user_paths $fish_user_paths ~/.rvm/bin worked for me

Dorian commented Jan 13, 2016

@yannickoo 👍 set --universal fish_user_paths $fish_user_paths ~/.rvm/bin worked for me

@timthelion

This comment has been minimized.

Show comment
Hide comment
@timthelion

timthelion Mar 12, 2016

Hm, well, I just did set --universal fish_user_paths $fish_user_paths ~/plan9/bin and ended up with a broken system :P so prepending $PATH isn't always the right thing™.

timthelion commented Mar 12, 2016

Hm, well, I just did set --universal fish_user_paths $fish_user_paths ~/plan9/bin and ended up with a broken system :P so prepending $PATH isn't always the right thing™.

@faho

This comment has been minimized.

Show comment
Hide comment
@faho

faho Mar 12, 2016

Member

@timthelion: In what way broken? Did you add it interactively or via config.fish (or similar)? (I'm asking because appending unconditionally to universal variables will cause them to blow up)

Or does your plan9 stuff just shadow something? Like e.g. it has an incompatible "grep"?

Member

faho commented Mar 12, 2016

@timthelion: In what way broken? Did you add it interactively or via config.fish (or similar)? (I'm asking because appending unconditionally to universal variables will cause them to blow up)

Or does your plan9 stuff just shadow something? Like e.g. it has an incompatible "grep"?

@timthelion

This comment has been minimized.

Show comment
Hide comment
@timthelion

timthelion Mar 12, 2016

Yes, it shadows almost everything, but it has extra commands as well, like venti and vac...

[00:06:26] timothy@timothy-debian-hp /home/timothy/plan9/bin (0)                          
> ls
"*           codereview.py*  gif*         ndbmkhosts*    rsagen*     tr*
""*          colors*         grap*        ndbquery*      sam*        tr2post*
9*           comm*           graph*       netfileget*    samsave*    tref*
9660srv*     core*           grep*        netfilelib.rc  samterm*    troff*
9a*          crop*           gunzip*      netfileput*    scat*       troff2html*
9ar*         date*           gview*       Netfiles*      secstore*   troff2png*
9c*          db*             gzip*        netfilestat*   secstored*  tweak*
9fs*         dc*             hget*        netkey*        secuser*    u*
9import*     dd*             hist*        news*          sed*        unicode*
9l*          delatex*        hoc*         nobs*          seq*        uniq*
9p*          deroff*         htmlfmt*     nroff*         sftpcache*  units*
9pfuse*      devdraw*        htmlroff*    osxvers*       sha1sum*    unmount*
9pserve*     dial*           ico*         p*             sig*        unutf*
9.rc*        dict*           iconv*       page*          slay*       unvac*
9term*       diff*           idiff*       passwd*        sleep*      unzip*
acid*        disk/           img*         pbd*           sort*       upas/
acidtypes*   disknfs*        import*      pemdecode*     spell*      u.rc*
acme*        dns*            ipso*        pemencode*     split*      usage*
acmeevent*   dnsdebug*       join*        pic*           sprog*      vac*
adict*       dnsquery*       jpg*         plot*          src*        vacfs*
aescbc*      dnstcp*         kill*        plumb*         srv*        vbackup*
ascii*       doctype*        label*       plumber*       ssam*       vcat*
asn12dsa*    dsa2pub*        lc*          png*           ssh-agent*  venti/
asn12rsa*    dsa2ssh*        lex*         ppm*           stack*      vmount*
astro*       dsagen*         listen1*     pr*            start*      vmount0*
auxclog*     dsasign*        look*        primes*        stats*      vnfs*
auxstats*    du*             lookman*     proof*         statusbar*  vwhois*
awd*         dump9660*       lpbin/       ps*            stop*       wc*
awk*         E*              ls*          psdownload*    strings*    web*
B*           echo*           Mail*        psfonts*       sum*        win*
basename*    ed*             man*         psu*           tail*       wintext*
bc*          eqn*            mapd*        psv*           tar*        wmail*
bmp*         factor*         mc*          ramfs*         tbl*        xd*
bundle*      factotum*       md5sum*      rc*            tcolors*    xshove*
bunzip2*     file*           mk*          read*          tcs*        yacc*
bzip2*       fmt*            mk9660*      readcons*      tee*        yesterday*
cal*         fortune*        mkdir*       resample*      test*       yuv*
calendar*    fossil/         mklatinkbd*  rio*           time*       zerotrunc*
cat*         freq*           mount*       rm*            togif*      zip*
cb*          fs/             mtime*       rsa2csr*       toico*
cleanname*   fsize*          namespace*   rsa2pub*       topng*
cmapcube*    g*              ndbipquery*  rsa2ssh*       toppm*
cmp*         Getdir*         ndbmkdb*     rsa2x509*      touch*
codereview*  getflags*       ndbmkhash*   rsafill*       tpic*

Now do you undestand what I mean by broken ;)

timthelion commented Mar 12, 2016

Yes, it shadows almost everything, but it has extra commands as well, like venti and vac...

[00:06:26] timothy@timothy-debian-hp /home/timothy/plan9/bin (0)                          
> ls
"*           codereview.py*  gif*         ndbmkhosts*    rsagen*     tr*
""*          colors*         grap*        ndbquery*      sam*        tr2post*
9*           comm*           graph*       netfileget*    samsave*    tref*
9660srv*     core*           grep*        netfilelib.rc  samterm*    troff*
9a*          crop*           gunzip*      netfileput*    scat*       troff2html*
9ar*         date*           gview*       Netfiles*      secstore*   troff2png*
9c*          db*             gzip*        netfilestat*   secstored*  tweak*
9fs*         dc*             hget*        netkey*        secuser*    u*
9import*     dd*             hist*        news*          sed*        unicode*
9l*          delatex*        hoc*         nobs*          seq*        uniq*
9p*          deroff*         htmlfmt*     nroff*         sftpcache*  units*
9pfuse*      devdraw*        htmlroff*    osxvers*       sha1sum*    unmount*
9pserve*     dial*           ico*         p*             sig*        unutf*
9.rc*        dict*           iconv*       page*          slay*       unvac*
9term*       diff*           idiff*       passwd*        sleep*      unzip*
acid*        disk/           img*         pbd*           sort*       upas/
acidtypes*   disknfs*        import*      pemdecode*     spell*      u.rc*
acme*        dns*            ipso*        pemencode*     split*      usage*
acmeevent*   dnsdebug*       join*        pic*           sprog*      vac*
adict*       dnsquery*       jpg*         plot*          src*        vacfs*
aescbc*      dnstcp*         kill*        plumb*         srv*        vbackup*
ascii*       doctype*        label*       plumber*       ssam*       vcat*
asn12dsa*    dsa2pub*        lc*          png*           ssh-agent*  venti/
asn12rsa*    dsa2ssh*        lex*         ppm*           stack*      vmount*
astro*       dsagen*         listen1*     pr*            start*      vmount0*
auxclog*     dsasign*        look*        primes*        stats*      vnfs*
auxstats*    du*             lookman*     proof*         statusbar*  vwhois*
awd*         dump9660*       lpbin/       ps*            stop*       wc*
awk*         E*              ls*          psdownload*    strings*    web*
B*           echo*           Mail*        psfonts*       sum*        win*
basename*    ed*             man*         psu*           tail*       wintext*
bc*          eqn*            mapd*        psv*           tar*        wmail*
bmp*         factor*         mc*          ramfs*         tbl*        xd*
bundle*      factotum*       md5sum*      rc*            tcolors*    xshove*
bunzip2*     file*           mk*          read*          tcs*        yacc*
bzip2*       fmt*            mk9660*      readcons*      tee*        yesterday*
cal*         fortune*        mkdir*       resample*      test*       yuv*
calendar*    fossil/         mklatinkbd*  rio*           time*       zerotrunc*
cat*         freq*           mount*       rm*            togif*      zip*
cb*          fs/             mtime*       rsa2csr*       toico*
cleanname*   fsize*          namespace*   rsa2pub*       topng*
cmapcube*    g*              ndbipquery*  rsa2ssh*       toppm*
cmp*         Getdir*         ndbmkdb*     rsa2x509*      touch*
codereview*  getflags*       ndbmkhash*   rsafill*       tpic*

Now do you undestand what I mean by broken ;)

@faho

This comment has been minimized.

Show comment
Hide comment
@faho

faho Mar 13, 2016

Member

Now do you undestand what I mean by broken ;)

Yes. And in this case prepending to PATH is definitely the wrong thing (like you said), but I'm not sure appending is much better. Of course it'd be nice to know what breaks, maybe we can fix it - which behavior do we rely on that the plan9 tools don't implement? I assume when they call something "mkdir" it makes directories, but it doesn't necessarily have a "-p" option.

Though my copy of the plan9port intro man page explicitly recommends against prepending to $PATH.

Member

faho commented Mar 13, 2016

Now do you undestand what I mean by broken ;)

Yes. And in this case prepending to PATH is definitely the wrong thing (like you said), but I'm not sure appending is much better. Of course it'd be nice to know what breaks, maybe we can fix it - which behavior do we rely on that the plan9 tools don't implement? I assume when they call something "mkdir" it makes directories, but it doesn't necessarily have a "-p" option.

Though my copy of the plan9port intro man page explicitly recommends against prepending to $PATH.

@floam

This comment has been minimized.

Show comment
Hide comment
@floam

floam Mar 13, 2016

Member

It does support mkdir -p, which is the most common result when grepping the source tree for system(, rm -Rf is the other one and that would fail as plan9's rm only recurses if given -r. Both are only used in the tests though so may not matter. Of course the brokenness in the library of .fish shell-scripts may be intense.

Member

floam commented Mar 13, 2016

It does support mkdir -p, which is the most common result when grepping the source tree for system(, rm -Rf is the other one and that would fail as plan9's rm only recurses if given -r. Both are only used in the tests though so may not matter. Of course the brokenness in the library of .fish shell-scripts may be intense.

@timthelion

This comment has been minimized.

Show comment
Hide comment
@timthelion

timthelion Mar 13, 2016

Well, I think that those utilities are provided in the plan9port in order to allow historic rc shell(plan9's own shell) scripts to work. Obviously, fish will never be (doesn't even want to be) compatible with those old plan9 shell scripts. So there is no reason to have access to those old utilities. However, that doesn't mean that a person wouldn't ever want to use plan9 utilities that don't exist in GNU posix or BSD... So for plan9port, in my opinion, it is best to append to the path and not prepend it. However, I understand that it would be unreasonable to change the behavior of $fish_user_paths just for plan9port ;). So my comment was more of a mater of interest. I ended up putting the appropriate commands in ~/.config/fish/config.fish.

timthelion commented Mar 13, 2016

Well, I think that those utilities are provided in the plan9port in order to allow historic rc shell(plan9's own shell) scripts to work. Obviously, fish will never be (doesn't even want to be) compatible with those old plan9 shell scripts. So there is no reason to have access to those old utilities. However, that doesn't mean that a person wouldn't ever want to use plan9 utilities that don't exist in GNU posix or BSD... So for plan9port, in my opinion, it is best to append to the path and not prepend it. However, I understand that it would be unreasonable to change the behavior of $fish_user_paths just for plan9port ;). So my comment was more of a mater of interest. I ended up putting the appropriate commands in ~/.config/fish/config.fish.

kc1212 added a commit to kc1212/dotfiles that referenced this issue Sep 29, 2016

hasit added a commit to hasit/yarn that referenced this issue Oct 11, 2016

Use a more modern way of setting $PATH in fish
Set `~/.yarn/bin` in `$fish_user_paths` instead of setting it in `~/.config/fish/config.fish` file.

See [suggestion from fish documentation](fish-shell/fish-shell#527 (comment)) for more reference.

cpojer added a commit to yarnpkg/yarn that referenced this issue Oct 12, 2016

Handle installation for 'fish' shell (#690)
* Handle installation for 'fish' shell

'fish' is a popular shell. This commit adds support for proper detection and installation of yarn in 'fish' shell. If the detected shell is 'fish', add path to ~/.yarn/bin in $HOME/.config/fish/config.fish file.

* Use a more modern way of setting $PATH in fish

Set `~/.yarn/bin` in `$fish_user_paths` instead of setting it in `~/.config/fish/config.fish` file.

See [suggestion from fish documentation](fish-shell/fish-shell#527 (comment)) for more reference.

* Run command to set $fish_user_paths instead of evaluating a string.
@nhooyr

This comment has been minimized.

Show comment
Hide comment
@nhooyr

nhooyr Oct 13, 2016

Contributor

How can you set fish_user_paths in shared dotfiles? Should I be using only $PATH instead?

Contributor

nhooyr commented Oct 13, 2016

How can you set fish_user_paths in shared dotfiles? Should I be using only $PATH instead?

@faho

This comment has been minimized.

Show comment
Hide comment
@faho

faho Oct 14, 2016

Member

@nhooyr: You could use $PATH, or you could add

if not set -q fish_user_paths[1]
    set -U fish_user_paths SOMEVAL
end

That being said, we should probably just remove the host part from the variable store. This is at least the third time in the last week this has come up.

Member

faho commented Oct 14, 2016

@nhooyr: You could use $PATH, or you could add

if not set -q fish_user_paths[1]
    set -U fish_user_paths SOMEVAL
end

That being said, we should probably just remove the host part from the variable store. This is at least the third time in the last week this has come up.

@nhooyr

This comment has been minimized.

Show comment
Hide comment
@nhooyr

nhooyr Oct 14, 2016

Contributor

@faho is there any advantage to using fish_user_paths for me?

Contributor

nhooyr commented Oct 14, 2016

@faho is there any advantage to using fish_user_paths for me?

@faho

This comment has been minimized.

Show comment
Hide comment
@faho

faho Oct 14, 2016

Member

@nhooyr: The nice thing about universal variables is that you can set-and-forget. Need another component in $PATH? Run set fish_user_paths $fish_user_paths /some/path once and you're done. It's even synced to every currently running shell on that machine.

Of course since the store is currently not something you can just keep in git and use across machines it loses a bit of its utility, and I set all of them via a config file because of that.

Member

faho commented Oct 14, 2016

@nhooyr: The nice thing about universal variables is that you can set-and-forget. Need another component in $PATH? Run set fish_user_paths $fish_user_paths /some/path once and you're done. It's even synced to every currently running shell on that machine.

Of course since the store is currently not something you can just keep in git and use across machines it loses a bit of its utility, and I set all of them via a config file because of that.

@nhooyr

This comment has been minimized.

Show comment
Hide comment
@nhooyr

nhooyr Oct 14, 2016

Contributor

@faho So no advantage for me right now because I need to sync across machines. Might as well use $PATH then. Thanks!

Contributor

nhooyr commented Oct 14, 2016

@faho So no advantage for me right now because I need to sync across machines. Might as well use $PATH then. Thanks!

@heyakyra

This comment has been minimized.

Show comment
Hide comment
@heyakyra

heyakyra Sep 19, 2017

I came here trying to figure out how to get Cabal for Haskell set up with fish.

What is the difference between:

set --universal fish_user_paths $fish_user_paths ~/.cabal/bin

and

set fish_user_paths $fish_user_paths ~/.cabal/bin

heyakyra commented Sep 19, 2017

I came here trying to figure out how to get Cabal for Haskell set up with fish.

What is the difference between:

set --universal fish_user_paths $fish_user_paths ~/.cabal/bin

and

set fish_user_paths $fish_user_paths ~/.cabal/bin

@mqudsi

This comment has been minimized.

Show comment
Hide comment
@mqudsi

mqudsi Sep 19, 2017

Contributor

It's the difference between set and set --universal, documented here: https://fishshell.com/docs/current/commands.html#set

-U or --universal causes the specified shell variable to be given a universal scope. If this option is supplied, the variable will be shared between all the current users fish instances on the current computer, and will be preserved across restarts of the shell.

In this case, since fish_user_paths is already defined as a universal variable (and is not explicitly shadowed in another scope), set fish_user_path ... will be as-if the same scope as the existing variable were applied to them (so an implicit --universal).

Contributor

mqudsi commented Sep 19, 2017

It's the difference between set and set --universal, documented here: https://fishshell.com/docs/current/commands.html#set

-U or --universal causes the specified shell variable to be given a universal scope. If this option is supplied, the variable will be shared between all the current users fish instances on the current computer, and will be preserved across restarts of the shell.

In this case, since fish_user_paths is already defined as a universal variable (and is not explicitly shadowed in another scope), set fish_user_path ... will be as-if the same scope as the existing variable were applied to them (so an implicit --universal).

@faho

This comment has been minimized.

Show comment
Hide comment
@faho

faho Sep 19, 2017

Member

@thekyriarchy: You'll want to see the fish documentation on "Shell variables" - specifically the "Variable scope" section (which is repeated in the set documentation).

In short: The former explicitly sets the universal variable. If that doesn't exist, it creates it. If it does, it modifies it - even if a variable of the same name exists in a different scope.

The latter will either modify the existing variable in the lowest scope (which could be local, global or universal - in that order), or it could create a function-scoped variable.

It's good form to explicitly specify the scope, so I'd recommend the former.

Member

faho commented Sep 19, 2017

@thekyriarchy: You'll want to see the fish documentation on "Shell variables" - specifically the "Variable scope" section (which is repeated in the set documentation).

In short: The former explicitly sets the universal variable. If that doesn't exist, it creates it. If it does, it modifies it - even if a variable of the same name exists in a different scope.

The latter will either modify the existing variable in the lowest scope (which could be local, global or universal - in that order), or it could create a function-scoped variable.

It's good form to explicitly specify the scope, so I'd recommend the former.

@heyakyra

This comment has been minimized.

Show comment
Hide comment
@heyakyra

heyakyra Sep 20, 2017

I tried both with and without --universal but either way it seems to not be preserved after reboots.

heyakyra commented Sep 20, 2017

I tried both with and without --universal but either way it seems to not be preserved after reboots.

@faho

This comment has been minimized.

Show comment
Hide comment
@faho

faho Sep 20, 2017

Member

@thekyriarchy: What is your setup? OS? fish version? What are the values of $HOME and $XDG_CONFIG_HOME?

If you echo $fish_user_paths right after starting fish, what does that print?

Member

faho commented Sep 20, 2017

@thekyriarchy: What is your setup? OS? fish version? What are the values of $HOME and $XDG_CONFIG_HOME?

If you echo $fish_user_paths right after starting fish, what does that print?

@krader1961

This comment has been minimized.

Show comment
Hide comment
@krader1961

krader1961 Sep 20, 2017

Contributor

@thekyriarchy, What version of fish are you running? What do the following commands output:

echo $HOME
ls -ld $HOME/.config/fish
ls -l $HOME/.config/fish
echo $XDG_CONFIG_HOME
ls -ld $XDG_CONFIG_HOME/.config/fish
ls -l $XDG_CONFIG_HOME/.config/fish
set -U | grep fish_user_paths
set -g | grep fish_user_paths
set -l | grep fish_user_paths
set -U | grep PATH
set -g | grep PATH
set -l | grep PATH
Contributor

krader1961 commented Sep 20, 2017

@thekyriarchy, What version of fish are you running? What do the following commands output:

echo $HOME
ls -ld $HOME/.config/fish
ls -l $HOME/.config/fish
echo $XDG_CONFIG_HOME
ls -ld $XDG_CONFIG_HOME/.config/fish
ls -l $XDG_CONFIG_HOME/.config/fish
set -U | grep fish_user_paths
set -g | grep fish_user_paths
set -l | grep fish_user_paths
set -U | grep PATH
set -g | grep PATH
set -l | grep PATH

jloh added a commit to jloh/fishtank that referenced this issue Dec 5, 2017

matthiasr added a commit to matthiasr/profile that referenced this issue Apr 6, 2018

Use fish_user_paths instead of manipulating PATH
fish-shell/fish-shell#527

handles the case nicely where one of them is already in PATH

Signed-off-by: Matthias Rampke <matthias@rampke.de>
@Mc128k

This comment has been minimized.

Show comment
Hide comment
@Mc128k

Mc128k Aug 12, 2018

Alternative solution, thanks to Google Cloud SDK:

Place the file path.bash.inc in the folder you want to add, e.g. the ~/go folder:

script_link="$( command readlink "$BASH_SOURCE" )" || script_link="$BASH_SOURCE"
apparent_sdk_dir="${script_link%/*}"
if [ "$apparent_sdk_dir" == "$script_link" ]; then
  apparent_sdk_dir=.
fi
sdk_dir="$( command cd -P "$apparent_sdk_dir" > /dev/null && command pwd -P )"
bin_path="$sdk_dir/bin"
export PATH=$bin_path:$PATH

Note that this appends the /bin folder, it's actually a good practice to put execs inside a folder named bin.

In fish config add the line:

bass source '/Users/yourUser/go/path.bash.inc'

This is nice, works everywhere

Mc128k commented Aug 12, 2018

Alternative solution, thanks to Google Cloud SDK:

Place the file path.bash.inc in the folder you want to add, e.g. the ~/go folder:

script_link="$( command readlink "$BASH_SOURCE" )" || script_link="$BASH_SOURCE"
apparent_sdk_dir="${script_link%/*}"
if [ "$apparent_sdk_dir" == "$script_link" ]; then
  apparent_sdk_dir=.
fi
sdk_dir="$( command cd -P "$apparent_sdk_dir" > /dev/null && command pwd -P )"
bin_path="$sdk_dir/bin"
export PATH=$bin_path:$PATH

Note that this appends the /bin folder, it's actually a good practice to put execs inside a folder named bin.

In fish config add the line:

bass source '/Users/yourUser/go/path.bash.inc'

This is nice, works everywhere

@NikhilVerma

This comment has been minimized.

Show comment
Hide comment
@NikhilVerma

NikhilVerma Oct 3, 2018

Just a warning to everyone here, I was bitten by this issue so I want to share

set fish_user_paths $fish_user_paths /some/path

If you do this your fish config cache will grow every single time you open your terminal, in my case it became several megabytes and the fish shell took ages to open.

The files are located in ~/.config/fish/fishd.xxx have a look at yours.

In my case the solution was to do

set fish_user_paths $PATH /some/path

NikhilVerma commented Oct 3, 2018

Just a warning to everyone here, I was bitten by this issue so I want to share

set fish_user_paths $fish_user_paths /some/path

If you do this your fish config cache will grow every single time you open your terminal, in my case it became several megabytes and the fish shell took ages to open.

The files are located in ~/.config/fish/fishd.xxx have a look at yours.

In my case the solution was to do

set fish_user_paths $PATH /some/path

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment