The Ultimate PATH Management Guide24 Jan 2017
Basics of Environment Variables and PATH
Each process has an environment, a set of variables that the process can read or write. When the process spawns another process, the new process inherits the environment of its parent. These values are nevertheless local: the child inherits a copy of the variables of the parent at creation-time. If the parent later changes his variables, the change will not be reflected on the child's variables.
One particularly interesting environment variable is called
PATH: it defines
the paths to search to find an executable specified by name. The value of this
variable is a list of paths separated by a separator (
: on Unix-based OSes
like Mac OS X and Linux,
; on Windows).
This is particularly relevant on the command line: when you type the name of a
program (for instance
ls in Unix), it will search the paths listed in the
PATH variable (from left to right) until it finds one containing a
We'll now see how each OS handles environment variables and the
particular question that will interest us is how the "default" value for the
environment variables (and the
PATH in particular) are set.
In Windows, the initial values for environment variables are stored in the registry.
These are separated between system values and user values. If a variable has
both a system and user value, the user value takes precedence, excepted for
the PATH, where both values get concatenated (user PATH,
;, system PATH).
- User environment variables are stored in
- System environment variables are stored in
explorer.exe will immediately reflect any change to these values, and any
program launched by it will inherit these values.
All other programs, on the other hand, need to be restarted. A few comments about programs of interest:
The Launchy app launcher automatically updates the environment before launching a program.
The ConEmu console emulator is by default configured to hijack the opening of new consoles and open them in the existing ConEmu window instead (this is a good thing). The problem that is when intercepting consoles opened by
explorer.exe, the environment seems to be set to that of the ConEmu window (i.e. the environment when a console was first launched). See this issue.
How to change the environment
Locally in a console: use the built-in set command. You can clear a variable by assigning it nothing:
From the explorer, follow these instructions.
Use the excellent Rapid Environment Editor
Running scripts on the command line
On Windows, it is customary to append an extension to executables binaries
.exe) and scripts (
.py, ...). However, typing this extension
to run the program is not very desirable.
There is an environment variable called
PATHEXT which holds a list of all
extensions that can be run on the command line. Basically, if a file has its
extension in this list, you can type its name ommitting the extension and it
will run as though you double clicked it. There might be some additional finesse
here, but it will be like this most of the time. The order of the extensions
PATHEXT is important if there are two files with the same name but
different extensions. Extensions earlier in the list have more priority.
Both Mac OS X and Linux are Unix-based OSes. As such, the basic principles of how environment variables are handled is similar. I'll explain this here before talking about the peculiarities of each OS.
In Unix, a process does not automatically inherit all the environment variables of its parents. It only inherits those that are explicitly exported.
In a shell script, or on the command line, we can mark a variable
X for export
export X. This can also be combined with the definition of the
export X="some stuff". You can un-export something with
Removing purely and simply a variable is done with
On Unix, environment variables are initialized by shell scripts. Some scripts are executed each time a shell is run. Which scripts are run depends on whether the shell is a login shell and wether it is interactive.
The rules are rather complex, but this page does a good job at summarizing them.
Also beware that your scripts may source other files, including those that mentionned in that guide.
When taking inheritance into account, usually the right thing to do is to define
your environment variables in
~/.profile or equivalent. One caveat: the file
won't get sourced when running a command remotely via SSH (that is, when running
a command through
ssh without creating an interactive shell).
Reloading the environment
Reloading the environment in an existing shell after you edited
be tricky. One easy solution would be to re-source
.profile, but there are a
.profileshould not have unwanted side-effects.
Often variables are not just set, but are modified. This is typically the
PATH, where you append to the existing definition.
In this case, if you reload the
.profile, you'll end up with many duplicate entries in your PATH, and you'll fail to clear entries you want removed.
Hence: no side-effects; set variables, don't modify them.
Mac OS X
OS X has a fantastic little utility called
path_helper that will help you
manage the PATH. Basically what it does is read the files in
appends their content to the PATH (one entry per line). Files are read in
lexicographic order, so you can control the order of entries in the PATH.
path_helper is not itself on the path, so you must call it through
its fully qualified name
/usr/libexec/path_helper. The output of
is a shell command to set the PATH. This command must itself be evaluated.
I suggest to define the following shell alias for ease of use:
alias refresh_path='eval `/usr/libexec/path_helper -s`'
-s part is just to ensure a bash-compatible command is generated.
By default, OS X calls
/etc/profile so you do not need to add
Oh and by the way,
path_helper does the same thing it does to
MANPATH (which holds the paths used to find manpages) but with the
Final word of caution:
/etc/paths.d requires root permission to write into.
However, the files must be readable without root permissions to be used by
path_helper. Hence you might need to do a
chmod 644 on the files you create
in that directory.
See this webpage for more details about
Setting the PATH for GUI applications
Ways of defining the PATH for GUI applications on OS X have a history of
breaking. You may read on the net about
launchd.conf, but those no longer works.
"The" solution, at the time of writing, is to create a file
~/Library/LaunchAgents/environment.plist, enter a bunch of boilerplate and
launchtl setenv commands to set environment variables.
See this explanation for details.
After a change, you can make it take effect with
launchctl load ~/Library/LaunchAgents/environment.plist (or wait for a reboot).
Once applied, new applications started from the Finder (or Spotlight) will
inherit the environment variables set in
Note that what
environment.plist does is simply run a script. You could use
that to actually source your
.profile or invoke
path_helper. Two solutions
that work with this idea (but doing rather more complicated things) are to be
found here and here.
The difficulty to achieve something so basic is truly baffling.
There are too many desktop managers for Linux to cover. Cursory searches seem to indicate that this aspect isn't too well thought-out however.
However, Linux should, in theory, be more scrupulous than OS X about
inheriting the PATH, even in GUI applications. Which means that, editing
.profile then login out and login in should work as a last resort.
Some distributions (notably Debian, Ubuntu, Fedora) have files called
/etc/environment where they recommend you define your
environment variables. The benefits of this way of doing things are rather
unclear, since it doesn't seem to enable anything that couldn't be done by
defining variables in