### Setup PATH
dirs=(
/usr/lib/ccache/bin # ccache
~/.local/script ~/.local/bin # My local scripts.
~/.local/gobin # GOBIN
/usr/local/bin /usr/local/sbin # local takes precedence
/bin /sbin /usr/bin /usr/sbin # Standard Unix
/usr/pkg/bin /usr/pkg/sbin # NetBSD
/usr/X11R6/bin /usr/X11R6/sbin # OpenBSD
/opt/ooce/bin # illumos
~/.local/share/gem/ruby/*/bin(N[-1]) # Ruby
~/.luarocks/bin(N[-1]) # Lua
~/.local/dotnet/root ~/.local/dotnet/tools # .NET
/usr/lib/plan9/bin # Plan 9 from userspace
~/code/Vim/gopher.vim/tools/bin # gopher.vim
~/.nimble/bin # Nim
~/.cargo/bin # Rust
~/.ghcup/bin # Haskell
)
typeset -U path=() # No duplicates
# Use full path so /bin and /usr/bin aren't duplicated if it's a symlink.
for d in $dirs:A; [[ -d $d ]] && path+=($d)
unset dirs d
typeset -U makes the $path array "unique", and :A ensures the full path is always used (in case of symlinks).You can probably do something similar with bash, but idk.
$path is tied to $PATH and an array, so you can use it as such for some of the other things:
print ${(F)path} | grep /bin # (F) to print one array per line
print ${(F)path} | sort # can also use (o) to print ordered PATH=$(perl -e 'print join ":", grep -d, split ":", $ENV{PATH}')
but that's because as a 20 year perl hacker and thus connoiseur of line noise, I'd rather read that than the shell clever.(this doesn't mean the shell clever is bad, it just means I don't find -that- dialect of line noise as skimmable)
% print doesnt-exist*
zsh: no matches found: doesnt-exist*
% print doesnt-exist*(N)
(doesn't print anything, pattern is just ignored)
([n]) is array indexing to get entry n; -1 gets the last entry: % print a*
a-1 a-2 a-3
% print a*([-1])
a-3
% print a*([1])
a-1
Globbing is automatically sorted by name.So putting that together, things like this:
~/.local/share/gem/ruby/*/bin(N[-1]) # Ruby
will use the latest Ruby version in ~/.local/share/gem/ruby, and it won't error out if it doesn't exist (so I can freely copy this around even to machines without Ruby, or remove Ruby, etc).- Use `~/.zprofile` to set the PATH and EDITOR environment variables. - Use `~/.zshrc` for aliases and a custom prompt, or anything tweaking the appearance and behavior of the terminal.
It seems the advantage of the `~/.zprofile` file versus `~/.zshenv` is that it sets environment variables such as `$PATH` without override from macOS. It seems the `~/.zshrc` file could be used for `$PATH` but, by convention and design, is intended for customizing the look and feel of the interactive terminal.
Frankly, saying `~/.zprofile` is better than `~/.zshrc` for setting `$PATH` only "by convention and design" feels like a cop-out. Wondering if anyone knows better.
In your guide, under ~/.zshenv, you mention that "macOS overrides this for PATH settings for interactive shells", without mentioning why or how. What's happening is that macOS sets your path in /etc/zprofile.
It seems your guide is missing a few global configfiles :) This is the order for an interactive login shell [1]:
/etc/zshenv
${ZDOTDIR:-$HOME}/.zshenv
/etc/zprofile (login)
${ZDOTDIR:-$HOME}/.zprofile (login)
/etc/zshrc (interactive)
${ZDOTDIR:-$HOME}/.zshrc (interactive)
/etc/zlogin (login)
${ZDOTDIR:-$HOME}/.zlogin (login)
/etc/zlogout (login - loaded on logout)
${ZDOTDIR:-$HOME}/.zlogout (login - loaded on logout)
In fact, the configfiles you mention are only loaded the way you've mentioned them, if the option GLOBAL_RCS is unset. And if GLOBAL_RCS is unset, macOS does not override your PATH, because/etc/zprofile is not loaded :)https://systemweakness.com/linux-privilege-escalation-using-...
Should it be `justpath --contains .`?
Opened issue here: https://github.com/epogrebnyak/justpath/issues/10