6 April 2021

Linux systems use lots of environment variables. Among others, there are variables that store your username ($USER) and the current directory ($PWD). One of the more important variables is $PATH. It tells the shell where programs and scripts are stored. If you try to run a script and you get a “command not found” error then the issue may be that the script isn’t in your PATH.

Where do binaries live?

On Linux, many common utilities are kept in the /usr/bin directory:

$ type awk
awk is /usr/bin/awk

The output of the type command shows that the Awk utility’s binary is /usr/bin/awk. To run an Awk command you don’t need to enter the full path to the binary though. Instead of, say, /usr/bin/awk --version you can simply run awk --version:

$ awk --version
GNU Awk 4.0.2

This works because /usr/bin is in the $PATH variable. To view the variable you can simply run echo $PATH. The output is not very readable (it is a long colon-separated string) but we can use a little trick to print each path on its own line:

$ echo "${PATH//:/$'\n'}"
/usr/local/cpanel/3rdparty/lib/path-bin
/usr/local/bin
/usr/bin
/usr/local/sbin
/usr/sbin
/opt/cpanel/composer/bin
/home/example/.local/bin
/home/example/bin

As you can see, /usr/bin is in our path. There are also two directories in my home folder: /home/example/.local/bin and /home/example/bin. This is where I can store any custom scripts I might want to run.

It is worth noting that the ~/bin and ~.local/bin directories may not exist. If they don’t, you can simply create the directories and put any executable scripts in it.

Changing your PATH

You can change the $PATH variable by setting a new PATH in your ~/.bashrc file. This can be useful if you need to add a directory to the PATH.

For instance, let’s imagine that you got a directory named /home/example/scripts that contains executable scripts. To add the directory to your PATH you can append it as follows:

echo "export PATH=\$PATH:/home/example/scripts" >> /home/example/.bashrc
source /home/example/.bashrc

The first commands adds the following line to the bottom of the .bashrc file:

export PATH=\$PATH:/home/example/scripts

I then “sourced” the file. This simply reloads the Bash configuration file. Without the source command you would have to log out and log back in before $PATH is updated.

PATH order

The order of the directories in your PATH is important. When you execute a command the shell looks for the binary in the order specified in the variable. For instance, when I run the command ls the shell checks the PATH and starts hunting for the ls binary. It first looks in /usr/local/cpanel/3rdparty/lib/path-bin, then in /usr/local/bin, and so forth. It is the sort of repetitive stuff computers excel at.

The shell stops looking as soon as the binary is found. This is why directories in your home folder are always last in your PATH. It avoid user errors (guess what happens if you have a script named named ls). And it also good security practice. If your account gets compromised then the attacker could add malicious binaries in your bin directory. As long as your bin directory is at the end of the PATH such binaries won’t override system binaries such as ls.

Other environment variables

The PATH variable is one of many environment variables. You can list all environment variables using the env command. Among the variables you might want to change is EDITOR. This variable defines what text editor is opened by utilities such as crontab (i.e. when you edit a crontab file). On most Linux systems the default editor is vi. If you are not familiar with vi then you can instead use the more friendly Nano editor:

$ echo $EDITOR
/usr/bin/vi

echo "export EDITOR=/usr/bin/nano" >> /home/example/.bashrc
source /home/example/.bashrc

$ echo $EDITOR
/usr/bin/nano