1. Overview
In this quick tutorial, we’ll focus on how to add a path to the Linux PATH variable in Bash and Zsh.
Since the methods we use for Bash work for Zsh as well, we’ll first address how to add a new path to the PATH variable in Bash.
Then we’ll explore some Zsh specific ways to do the job.
2. PATH Variable
The PATH variable is an environment variable containing an ordered list of paths that Linux will search for executables when running a command. Using these paths means that we don’t have to specify an absolute path when running a command.
For example, if we want to print Hello, world! in Bash, the command echo can be used rather than /bin/echo, so long as /bin is in PATH:
echo "Hello, world!"
Linux traverses the colon-separated paths in order until finding an executable. Thus, Linux uses the first path if two paths contain the desired executable.
We can print the current value of the PATH variable by echoing the PATH environment variable:
echo $PATH
We should see a list of colon-separated paths (exact paths may differ):
/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
3. Adding a New Path in Bash
We can add a new path to the PATH variable using the export command.
To prepend a new path, such as /some/new/path, we reassign the PATH variable with our new path at the beginning of the existing PATH variable (represented by $PATH):
export PATH=/some/new/path:$PATH
To append a new path, we reassign PATH with the new path at the end:
export PATH=$PATH:/some/new/path
4. Persisting Changes in Bash
When we use the export command and open a new shell, the added path is lost.
4.1. Locally
To persist our changes for the current user, we add our export command to the end of ~/.profile. If the ~/.profile file doesn’t exist, we should create it using the touch command:
touch ~/.profile
Then we can add our export command to ~/.profile.
Additionally, we need to open a new shell, or source our ~/.profile file to reflect the change. We’d execute:
. ~/.profile
Or if we’re using Bash, we could use the source command:
source ~/.profile
We could also append our export command to ~/.bash_profile if we’re using Bash, but our changes won’t be reflected in other shells, such as Zsh.
We shouldn’t add our export command to ~/.bashrc because only interactive Bash shells read this configuration file. If we open a non-interactive shell or a shell other than Bash, our PATH change won’t be reflected.
4.2. Globally
We can add a new path for all users on a Unix-like system by creating a file ending in .sh in /etc/profile.d/ and adding our export command to this file.
For example, we can create a new script file, /etc/profile.d/example.sh, and add the following line to append /some/new/path to the global PATH:
export PATH=$PATH:/some/new/path
All of the scripts in /etc/profile.d/ will be executed when a new shell initializes. Therefore, we need to open a new shell for our global changes to take effect.
We can also add our new path directly to the existing PATH in the /etc/environment file:
PATH=<existing_PATH>:/some/new/path
The /etc/environment file isn’t a script file, it only contains simple variable assignments, and it’s less flexible than a script. Because of this, making PATH changes in /etc/environment is discouraged. We recommend adding a new script to /etc/profile.d instead.
5. $PATH in Zsh
Zsh is getting popular, since it provides a rich set of excellent features. Now let’s see how to add a new path in Zsh.
5.1. Adding a New Path Entry in Zsh
So far, we’ve learned methods for adding a new path in Bash. First of all, these methods work for Zsh too.
If our shell is Zsh, we can append a new path to the $PATH variable in the array way:
zsh% echo $PATH
/usr/local/bin:/usr/bin:/bin
zsh% path+=/a/new/path
zsh% echo $PATH
/usr/local/bin:/usr/bin:/bin:/a/new/path
As the example above shows, we used path+=/a/new/path* to append a new path to *$PATH. Please note that we used the lower case path+=….
This is because path is an array. It also affects its upper-case partner equivalent $PATH. Zsh has bound these two with typeset builtin by default.
Similarly, we can prepend a new path in the array way too:
zsh% path=('/another/new/path' $path)
zsh% echo $PATH
/another/new/path:/usr/local/bin:/usr/bin:/bin:/a/new/path
However, *after adding the new entry to the path array, we shouldn’t forget “export $PATH,” as we did in Bash*.
5.2. Persisting Changes
For compatibility, Zsh first sources .profile, then sources zshenv and zshrc. That is to say, the settings in zshenv and zshrc may override configurations in .profile. Therefore, for Zsh, it would be good if we put settings in Zsh specific configuration files.
Similar to the bashrc file, /etc/zshrc or ~/.zshrc is only for the interactive shell. So it’s not an ideal place to store $PATH.
Thus, if we want all Zsh users to have the $PATH setting, effectively setting $PATH globally, we can put it in /etc/zshenv. It’s worth mentioning that this file may not exist, and we can create it if we want to set something globally.
On the other hand, if we would like to set $PATH for our user only, we can put $PATH in ~/.zshenv.
6. Conclusion
In this article, we learned how Linux uses the PATH variable to find executables when running a command.
We can prepend or append to PATH, but to persist these changes, we need to put the PATH configuration in the right configuration file.
This table can summarize it clearly:
Local
Global
Bash
~/.profile
A .sh file in /etc/profile.d
Zsh
~/.zshenv
/etc/zshenv