That's a feature of zsh
inherited from csh
/tcsh
.
The $path
array variable is tied to the $PATH
scalar (string) variable. Any modification on one is reflected in the other.
In zsh
(contrary to (t)csh
), you can tie other variables beside $PATH
with typeset -T
. It's conventional, but not mandatory, to use an uppercase name for the colon-separated scalar and the same name in lowercase for the array. While colon is the default separator, other separators can be used (for instance newline to tie a multi-line string to an array, or comma to tie a csv row to an array)
In recent versions of zsh
, typeset -p PATH
or typeset -p path
shows the link between the two variables:
% typeset -p path
typeset -aT PATH path=( /home/chazelas/bin /usr/local/bin /usr/bin /bin )
That's useful in that it makes it easier to add remove components or loop over them.
Doing a typeset -U path
to make the elements unique also helps keeping the $PATH
variable clean (something similar can be achieved in tcsh
with set -f
).
For completeness, fish
and yash
are two other shells that can treat $PATH
as an array, though in their case, that's not via a separate lowercase variable.
In fish
, variables whose name ends in PATH
are treated as lists implicitly split/joined on colons, so set PATH /foo /bar
and set PATH /foo:/bar
are equivalent there.
In yash
, exporting an array to the environment results in the value of the environment variable containing the elements joined with a colon. So you can do PATH=(/foo /bar)
there. Note that when importing $PATH
from the environment upon start, yash
does not automatically create it as an array.
path
insidezsh
will not update anypath
envvar:path=junk zsh -c 'echo $path; path=garbage; /usr/bin/printenv path'
.for path in "$dir"/*
reflexively safe-to-write code.