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
How to Tar a Directory Without Retaining the Directory Structure
Where Is the X86-64 System V Abi Documented
How to Pass Command Output as Multiple Arguments to Another Command
How to Get Overall Cpu Usage (E.G. 57%) on Linux
Simulate Delayed and Dropped Packets on Linux
More Elegant "Ps Aux | Grep -V Grep"
The Difference Between Fork(), Vfork(), Exec() and Clone()
Can Awk Patterns Match Multiple Lines
How to Create a File With a Given Size in Linux
How to Syntax Check a Bash Script Without Running It
Change the X-Frame-Options to Allow All Domains
How to Keep Environment Variables When Using Sudo
How to 'Grep' a Continuous Stream
How to Link to a Specific Glibc Version
Using Awk to Print All Columns from the Nth to the Last
How to Access Physical Addresses from User Space in Linux