Adding a New Entry to the Path Variable in Zsh

Adding a new entry to the PATH variable in ZSH

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.

How can I change PATH variable in zsh?

The .zshrc is located in the home dir. The dot at the beginning keeps it hidden. Type ls -a from ~ directory to see it. To edit just run vim, nvim, etc as usual.

nvim ~/.zshrc

This is the command for Neovim. For your editor, sub nvim for the proper command.

Once you get in, you need only add the same export command that you would add from the command line.

export PATH=$PATH:/whatever/you/are/adding

EDIT

To remove a path variable:

  • First, run the command:
echo $PATH

from the command line.

  • Next, Copy the output to clipboard.

  • Finally, at the very end of the .zshrc file, add the following:

export PATH=<paste-what-you-copied-here>

Because you didn't reference $PATH after the =, this will set the path to EXACTLY what you pasted, no more, no less. Adding $PATH: as in the first example will just add whatever to the end of what is already there.

Since this gives you access to every item in the path array, deleting is just a matter of a literal highlight/select and of whatever you want deleted.

Finally, be sure that there is only one place in the file where you are editing PATH. If there are more than one, the result can be confusing to say the least.

That said, I believe the script runs top-to-bottom, so only the last mention should persist. You can take advantage of this in some situations, but for this purpose, one will suffice. XD

ZSH PATH variable entries are backwards on OS X Catalina

I suspect the issue is that .zshenv executes before any other startup files, which are also modifying PATH. (This isn't a full explanation, as /etc/zprofile should be overwriting PATH, not prepending to it. But it's close.)

Instead of setting PATH in .zshenv (which is sourced for all shells, interactive or not), do it in ~/.zprofile instead.

See the section on startup/shutdown files in man zsh for a full explanation of which files are sourced and when.

zsh using a variable in a command within a function

I don't see the point in using $@ in your function, since you expect only one argument. $1 would be sufficient.

The problem is in the tilde which is contained in your variable SITEPATH. You need to have it expanded. You can either do it by writing

export SITESPATH=~/path/to/parent/directory

when you define the variable, or inside your function by doing a

cd ${~SITESPATH)/$1

A third possibility is to turn on glob_subst in your shell:

setopt glob_subst

In this case, you can keep your current definition of $SITESPATH, and tilde-substitution will happen automatically.

How to edit path variable in ZSH

Unlike other shells, zsh does not perform word splitting or globbing after variable substitution. Thus $PATHDIRS expands to a single string containing exactly the value of the variable, and not to a list of strings containing each separate whitespace-delimited piece of the value.

Using an array is the best way to express this (not only in zsh, but also in ksh and bash).

pathdirs=(
/usr/local/mysql/bin

~/bin
)
for dir in $pathdirs; do
if [ -d $dir ]; then
path+=$dir
fi
done

Since you probably aren't going to refer to pathdirs later, you might as well write it inline:

for dir in \
/usr/local/mysql/bin \
… \
~/bin
; do
if [[ -d $dir ]]; then path+=$dir; fi
done

There's even a shorter way to express this: add all the directories you like to the path array, then select the ones that exist.

path+=/usr/local/mysql/bin

path=($^path(N))

The N glob qualifier selects only the matches that exist. Add the -/ to the qualifier list (i.e. (-/N) or (N-/)) if you're worried that one of the elements may be something other than a directory or a symbolic link to one (e.g. a broken symlink). The ^ parameter expansion flag ensures that the glob qualifier applies to each array element separately.

You can also use the N qualifier to add an element only if it exists. Note that you need globbing to happen, so path+=/usr/local/mysql/bin(N) wouldn't work.

path+=(/usr/local/bin/mysql/bin(N-/))

Where to place $PATH variable assertions in zsh?

tl;dr version: use ~/.zshrc

And read the man page to understand the differences between:

~/.zshrc, ~/.zshenv and ~/.zprofile.


Regarding my comment

In my comment attached to the answer kev gave, I said:

This seems to be incorrect - /etc/profile isn't listed in any zsh documentation I can find.

This turns out to be partially incorrect: /etc/profile may be sourced by zsh. However, this only occurs if zsh is "invoked as sh or ksh"; in these compatibility modes:

The usual zsh startup/shutdown scripts are not executed. Login shells source /etc/profile followed by $HOME/.profile. If the ENV environment variable is set on invocation, $ENV is sourced after the profile scripts. The value of ENV is subjected to parameter expansion, command substitution, and arithmetic expansion before being interpreted as a pathname. [man zshall, "Compatibility"].

The ArchWiki ZSH link says:

At login, Zsh sources the following files in this order:

/etc/profile

This file is sourced by all Bourne-compatible shells upon login

This implys that /etc/profile is always read by zsh at login - I haven't got any experience with the Arch Linux project; the wiki may be correct for that distribution, but it is not generally correct. The information is incorrect compared to the zsh manual pages, and doesn't seem to apply to zsh on OS X (paths in $PATH set in /etc/profile do not make it to my zsh sessions).



To address the question:

where exactly should I be placing my rvm, python, node etc additions to my $PATH?

Generally, I would export my $PATH from ~/.zshrc, but it's worth having a read of the zshall man page, specifically the "STARTUP/SHUTDOWN FILES" section - ~/.zshrc is read for interactive shells, which may or may not suit your needs - if you want the $PATH for every zsh shell invoked by you (both interactive and not, both login and not, etc), then ~/.zshenv is a better option.

Is there a specific file I should be using (i.e. .zshenv which does not currently exist in my installation), one of the ones I am currently using, or does it even matter?

There's a bunch of files read on startup (check the linked man pages), and there's a reason for that - each file has it's particular place (settings for every user, settings for user-specific, settings for login shells, settings for every shell, etc).

Don't worry about ~/.zshenv not existing - if you need it, make it, and it will be read.

.bashrc and .bash_profile are not read by zsh, unless you explicitly source them from ~/.zshrc or similar; the syntax between bash and zsh is not always compatible. Both .bashrc and .bash_profile are designed for bash settings, not zsh settings.



Related Topics



Leave a reply



Submit