Adding a new entry to the PATH variable in ZSH

400,560

Solution 1

Here, add this line to .zshrc:

export PATH=/home/david/pear/bin:$PATH

EDIT: This does work, but ony's answer above is better, as it takes advantage of the structured interface ZSH provides for variables like $PATH. This approach is standard for bash, but as far as I know, there is no reason to use it when ZSH provides better alternatives.

Solution 2

Actually, using ZSH allows you to use special mapping of environment variables. So you can simply do:

# append
path+=('/home/david/pear/bin')
# or prepend
path=('/home/david/pear/bin' $path)
# export to sub-processes (make it inherited by child processes)
export PATH

For me that's a very neat feature which can be propagated to other variables. Example:

typeset -T LD_LIBRARY_PATH ld_library_path :

Solution 3

You can append to your PATH in a minimal fashion. No need for parentheses unless you're appending more than one element. It also usually doesn't need quotes. So the simple, short way to append is:

path+=/some/new/bin/dir

This lower-case syntax is using path as an array, yet also affects its upper-case partner equivalent, PATH (to which it is "bound" via typeset).

(Notice that no : is needed/wanted as a separator.)

Common interactive usage

Then the common pattern for testing a new script/executable becomes:

path+=$PWD/.
# or
path+=$PWD/bin

Common config usage

You can sprinkle path settings around your .zshrc (as above) and it will naturally lead to the earlier listed settings taking precedence (though you may occasionally still want to use the "prepend" form path=(/some/new/bin/dir $path)).

Related tidbits

Treating path this way (as an array) also means: no need to do a rehash to get the newly pathed commands to be found.

Also take a look at vared path as a dynamic way to edit path (and other things).

You may only be interested in path for this question, but since we're talking about exports and arrays, note that arrays generally cannot be exported.

You can even prevent PATH from taking on duplicate entries (refer to this and this):

typeset -U path

PATH pre-populated

The reason your path already has some entries in it is due to your system shell files setting path for you. This is covered in a couple other posts:

Solution 4

one liner, without opening ~/.zshrc file

echo -n 'export PATH=~/bin:$PATH' >> ~/.zshrc

or

echo -n 'export PATH=$HOME/bin:$PATH' >> ~/.zshrc

To see the effect, do source ~/.zshrc in the same tab or open a new tab

Solution 5

  1. Added path to ~/.zshrc

    sudo vi ~/.zshrc

    add new path

    export PATH="$PATH:[NEW_DIRECTORY]/bin"
    
  2. Update ~/.zshrc

    Save ~/.zshrc

    source ~/.zshrc

  3. Check PATH

    echo $PATH

Share:
400,560
David Barreto
Author by

David Barreto

I'm an Electronic Engineer by proffesion but a Software Developer by passion. I was born in Maracaibo (Venezuela) but I'm currently living in Toronto (Canada). I've worked with many different languages (HTML, CSS, Javascript, PHP, MySQL, MongoDB) and frameworks (Symfony2, JQuery, JQuery UI, Mootools, Twitter Bootstrap, AngularJS, Angular2) and I feel as confortable working in the front as in the backend of an application.

Updated on February 05, 2022

Comments

  • David Barreto
    David Barreto about 2 years

    I'm using zsh and I'm trying to add a new entry (/home/david/pear/bin) to the PATH variable but I don't know how.

    The thing that confuses me the most is that there's not a single reference to a PATH variable in my ~/.zshrc file, but doing echo $PATH returns:

    /usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
    

    So a PATH variable is being set somewhere.

  • David Barreto
    David Barreto almost 12 years
    haha forget it, I though that was only a console command but adding that line to the .zshrc did the trick. Thanks a lot!
  • Zack Huston
    Zack Huston about 10 years
    My .zshrc already had a line for export PATH so I replaced it with the modified one.
  • Khanh Nguyen
    Khanh Nguyen almost 10 years
    Nice answer. In my case, ~/.zshrc is sourced after .profile, and overwrites everything in .profile. Took a while pulling my hair to figure it out.
  • a7omiton
    a7omiton about 9 years
    I had to remove the double quotes around the entries i.e. PATH="/home/david/pear/bin:/usr/bin:etc" to PATH=/home/david/pear/bin:/usr/bin:etc for it to stay in zshrc.
  • Micah Elliott
    Micah Elliott almost 9 years
    The append case does does not need the parens unless you're appending more than one element. It also often doesn't need the quotes. So the simple, short way to append is
  • mencargo
    mencargo over 8 years
    @taco, you can use $HOME
  • ony
    ony about 8 years
    @SuperUberDuper, you should understand that almost any unix shell simply reads startup files which does almost the same as if you'd type it into shell interactively. Regarding "rc" files you might find interesting answer to this question
  • sstruct
    sstruct over 7 years
    It will erase all the old PATH, try export PATH=$PATH:/path/to/dir
  • Grief
    Grief about 7 years
    It's possible to avoid explicit export with -x and leave only unique values in a variable with -U, colon is assumed by default, so it can be: typeset -TUx PATH path
  • andrew lorien
    andrew lorien over 6 years
    Should it not be 'path+=:/foo/bar'? (with a colon)
  • Micah Elliott
    Micah Elliott over 6 years
    @andrewlorien I updated the answer with details about the colon separator.
  • Stryker
    Stryker about 6 years
    Worked perfecly on OSX with Zsh shell.
  • Franklin Yu
    Franklin Yu about 5 years
    Note that if there’s a comment after the path, then we do need quotes, like path+='my/path' # for fun. It’s obvious if you have spaces, but not so much if you have comments.
  • Franklin Yu
    Franklin Yu about 5 years
    Can you elaborate on how this answer is different from the same answer posted 5 years ago?
  • Dimitar
    Dimitar about 5 years
    in this answer it is not said that you have to add this line of code to the file, if you just run it like that it will change only in the current windows and this is not explain in the original answer
  • Akbarsha
    Akbarsha about 5 years
    Worked like a charm!
  • CousinCocaine
    CousinCocaine over 4 years
    I see the use of path and PATH, both are separate entities?
  • CousinCocaine
    CousinCocaine over 4 years
    This is the Bash way.
  • ony
    ony over 4 years
    @CousinCocaine, you are right. ZSH variables are case-sensitive. typeset -T allows to tie PATH and path together in a special way that internally ZSH manages array variable path and reflects its contents in PATH as a scalar.
  • Dani
    Dani over 4 years
    This appends to my existing PATH, and every time it's run, appends again. How do I set exactly what PATH should be?
  • Dani
    Dani over 4 years
    How do I set exactly what PATH should be, as opposed to appending to it? Because every time .zshrc is executed, PATH gets whatever is declared in .zshrc appended to it again and again.
  • Linuxios
    Linuxios over 4 years
    You can set PATH directly @DanielSpringer: export PATH=/some/where:/bin:/usr/bin and so on. Is that what you're asking? The idea is to run the code in this answer in the .zshrc or .profile or something like that at the beginning of each session.
  • Linuxios
    Linuxios over 4 years
    @DanielSpringer: Yes. When you open a shell it inherits PATH from the parent process that started it, and then when it runs .zshrc (or .bashrc or whatever), that's what lets you add extra things to that path.
  • Linuxios
    Linuxios over 4 years
    @DanielSpringer: Worth noting that you have to add the folder they're in to your path, not the path to the script file itself.
  • Dani
    Dani over 4 years
    @Linuxios Ah, and do I need to add the path to the file itself too, or just its folder?
  • Linuxios
    Linuxios over 4 years
    Just the folder. PATH is a list of places (folders; directories) where the shell will look for commands you try to run. For example, when you run wget ... the shell is looking for and finding the wget binary in /usr/bin, for example, which is in the default PATH.
  • ony
    ony over 4 years
    @DanielSpringer, there is a hint in second example. By just writing path=(...) you get it set. You might be interested as well in comment from @Grief about -U. And I'd recommend modifying PATH environment from ~/.*profile-like files so they will not execute when you run inner shell. See also something like shreevatsa.wordpress.com/2008/03/30/… or other similar tips.
  • Dani
    Dani over 4 years
    It seems that "path=" appends to path rather then setting it. What I didn't know is that path is reset upon relaunching Terminal/Shell/(maybe?)Login session
  • ony
    ony over 4 years
    @DanielSpringer, no. If you want it in those terms then: path=(...) (without referencing $path or $PATH inside) assigns, path=(... $path) prepends and path+(...) appends.
  • caram
    caram over 4 years
    You can even have it as 1-liner: export path=(... $path).
  • Randy
    Randy almost 4 years
    This doesn't work for me on my mac. I use the one liner answer below that updates ~/.zshrc insead.
  • Emmett R.
    Emmett R. almost 4 years
    "(Notice that no : is needed/wanted as a separator.)" This is only true for a lowercase path. A preceding : is required for PATH, as follows in .zshrc PATH+=:/Users/path/to/my/folder
  • Timo
    Timo over 3 years
    I use a lot exec zsh because I work with plugins from oh-my-zsh.Everytime I do exec the path gets bigger. Should I "default" the path from time to time?
  • Milan Tarami
    Milan Tarami over 3 years
    effective way to do
  • Timo
    Timo over 3 years
    @KhanhNguyen how can I see when these files are sourced? Is there a cmd?
  • ony
    ony over 3 years
    @Timo, in case of zsh you can try something like zsh -x -i -l -c true to see all commands during shell start-up. That -l is to simulate login-like start (as it happens from text VT or over ssh). But you should understand that not always zsh will be started as login (e.g. graphical session) and some other parent process may somehow source .profile before spawning non-login zsh sub-process that inherits environment variables (including PATH) from parent process.
  • Rotkiv
    Rotkiv over 3 years
    What if i want to use $HOME inside ' '? path +=('$HOME/etc/etc') doesn't seem to work
  • ony
    ony about 3 years
    @Rotkiv, that's a bit different question about how single/double quotes are interpreted. I guess zsh expansion covers this. Usually double-quotes allow string interpolation like "$HOME/etc/etc", but single quotes makes it easier to represent text that should not get special treatment. Note that you can always mix in a single argument forms to have something like "$HOME"'/etc/etc' (double + single quotes) or "$HOME"/etc/etc (double quotes + unquoted). P.S. Yes I'm lazy to try find link to good answer on SO :P
  • Jost
    Jost about 3 years
    On macOS, you can prepend and append to your path variable as described in the post, adding to the .zshrc file. It works without exporting the PATH.
  • Hamza Waleed
    Hamza Waleed almost 3 years
    Just a side note, if your path has a space in it. then you need to wrap your path in double quotes like this: export PATH=$PATH:"/Applications/Android Studio.app/Contents"
  • Yerke
    Yerke almost 3 years
    If this append or prepend syntax doesn't work for you, make sure that you are using lower case path. Lower case path is the array.
  • C. Sederqvist
    C. Sederqvist almost 3 years
    For ZSH to interpret $PATH as an array and make it unique, I believe the correct way would be typeset -aU path
  • MEMark
    MEMark over 2 years
    Thank you for showing the prepend as well! Didn't see it anywhere else.
  • Minh Nghĩa
    Minh Nghĩa over 2 years
    This does not seem to work with ~.
  • Phil
    Phil over 2 years
    This didn't work for me even though things looked absolutely fine when I echo $PATH. I had to go back to the "traditional" syntax of something like: export PATH=$ANDROID_HOME/platform-tools:$PATH
  • ony
    ony over 2 years
    @MinhNghĩa, ~ is expanded by shell. If you put it in quotes like '~/bin' or "~/bin" it will be literally tilda in your path. E.g. you can write path+=(~/bin) (note no quotes) or similar. If you need to quote something, you still can do it on part like path+=(~/'some path with spaces').
  • ony
    ony over 2 years
    @Phil, my best guess for your case is that ok result of echo $PATH shows your current shell value for it. Any chance it works if you do export PATH (upper case) to export for sub-process after setting path (lower case)?