Skip to content

Path#

Let's look at this variable's value: echo $PATH

Note

This environment variable should be mostly identical to mine provided you're just using a simple, clean Ubuntu installation. There may be some variation, though. Don't worry about it.

1
2
michael@develop:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

Notice how I use $ before the variable name? Try this: echo PATH

1
2
michael@develop:~$ echo PATH
PATH

The $ symbol before the name tells the shell, Bash in our case, that what you're looking for is the value inside of the variable ($) called PATH, hence $PATH.

Let's look at the value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin - that's a list of file system paths separated with a colon (:). Let's break it up into an actual list:

  • /usr/local/sbin
  • /usr/local/bin
  • /usr/sbin
  • /usr/bin
  • /sbin
  • /bin
  • /usr/games
  • /usr/local/games
  • /snap/bin

Yep! That's a list of file system paths. These are absolute paths, not relative, because they have a / at the beginning and not a . or .. at the beginning. But why is this particular variable important or even useful?

Because when you type a command into the shell, a few things happen and among them are:

  1. The shell looks to see if what you typed is an internal command like alias
  2. If it's not, it looks for the command by looping over each item in $PATH and appending the command to it

In step (1), an internal command is a command that the shell (like Bash) provides, like alias. Sometimes an executable you can find in the directories inside of $PATH has the same name. If that's the case, and you don't want to run the shell version of the command, you can use \alias.

In step (2), the shell will loop over the directories in the $PATH, each separated with a : (colon) and append the command you asked for, like this:

  • /usr/local/sbin/fake_command (not found)
  • /usr/local/bin/fake_command (found! - stops looking)
  • /usr/sbin/fake_command
  • /usr/bin/fake_command
  • /sbin/fake_command
  • /bin/fake_command
  • /usr/games/fake_command
  • /usr/local/games/fake_command
  • /snap/bin/fake_command

It found the fake_command in the path /usr/local/bin/. Now it'll execute that file and hopefully you get your results!

The reason the $PATH variable is so powerful, and used so often, is because people tend to install software locally outside of the directories listed inside the $PATH variable. That means if you type new_command it's not going to get executed because the shell environment cannot find it.

To resolve that, we update the $PATH to include where we've installed the new_command executable. Let's do this for real!

Here's my $PATH right now:

1
2
michael@develop:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

Now let's create a new executable script:

1
2
3
4
5
michael@develop:~$ cat <<EOF > new_command
> #!/bin/bash
> echo "New command"
>
> EOF

Note

Don't worry about specific commands here.

So we've created a file called new_command and it contains a simple script. Can I execute it? No, and for two good reasons:

  1. The x permission is missing from it, so it can never be executed
  2. It's located inside of ~ (which is our home, remember?), so it's not in $PATH

The first problem we can fix with ease: chmod u+x new_command

1
2
michael@develop:~$ ls -l new_command
-rwxrw-r-- 1 michael michael 32 Mar 22 22:57 new_command

Now it's executable by me, and me alone.

Let's try now: new_command

1
2
michael@develop:~$ new_command
new_command: command not found

Let's fix that: PATH=$PATH:/home/michael/

1
2
3
michael@develop:~$ PATH=$PATH:/home/michael/
michael@develop:~$ new_command
New command

Nice. But try logging out and back in again: command not found. How we changed/updated the $PATH variable, above, did not persist from one shell session to the next. We must update our bash_rc file as we learned earlier and then the change will persist.