How is my $PATH variable built on macOS?
I've recently installed Homebrew on my Mac and it's complaining that /usr/bin
occurs before /usr/local/bin
in my $PATH
variable, meaning that system-provided programs will be used instead of those installed with Homebrew.
My .bashrc
is configured in a set of separate files, as per this screencast. This means that ~/.bash_profile
looks like this:
if [ -f ~/.bashrc ];
then
source ~/.bashrc
fi
~/.bashrc
looks like this:
source ~/bin/dotfiles/bashrc
and ~/bin/dotfiles/bashrc
looks like this:
. ~/bin/dotfiles/bash/env
. ~/bin/dotfiles/bash/config
. ~/bin/dotfiles/bash/aliases
~/bin/dotfiles/bash/env
, which is where I set my $PATH
variable, looks like this:
export EDITOR="kom"
export PATH=some/path/at/start:usr/local/bin:/Users/jim/pear/bin:~/bin:/Users/jim/.gem/ruby/1.8/bin:/Users/jim/bin/bashscripts:some/path/at/end:$PATH
I've added some/path/at/start
and some/path/at/end
for debugging purposes, since when I try echo $PATH
I get this:
/opt/local/bin:/opt/local/sbin:/Users/jim/bin:/opt/local/bin:/opt/local/sbin:some/path/at/start:usr/local/bin:/Users/jim/pear/bin:/Users/jim/bin:/Users/jim/.gem/ruby/1.8/bin:/Users/jim/bin/bashscripts:some/path/at/end:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
That is, there's a load of other stuff being loaded into the $PATH variable that I can't control in the configuration I've outlined above. Any ideas as to where this stuff is loaded from, so that I can go about changing it and moving /usr/local/bin
before /usr/bin
?
Solution 1:
If you fix the typo in your PATH assignment and replace usr/local/bin
with /usr/local/bin
Homebrew should stop complaining.
The other stuff (/opt/local/...
) is definitively added somewhere later during shell initialization (meaning after source ~/.bashrc
or after . ~/bin/dotfiles/bash/env
). You will have to look through the different files (or grep for /opt/local
or PATH.*PATH
) to see where it happens (and why).
Solution 2:
The INVOCATION section of the bash man page says
When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable.
Of particular interest is /etc/profile
, which uses path_helper
to build a path from what it finds in /etc/paths
and /etc/paths.d/*
.
Solution 3:
There's also the system wide bashrc, which is found at /etc/bashrc, and a couple others.
From man bash
:-
FILES
/bin/bash
The bash executable
/etc/profile
The systemwide initialization file, executed for login shells
~/.bash_profile
The personal initialization file, executed for login shells
~/.bashrc
The individual per-interactive-shell startup file
~/.bash_logout
The individual login shell cleanup file, executed when a login shell exits
~/.inputrc
Individual readline initialization file