I often use a program called git
in my terminal.
When I type git
, my shell runs the program located at /usr/local/bin/git
.
I found that out just now by running the command which git
:
[I] ⋊> ~ which git
/usr/local/bin/git
if you're following along, bear in mind:
- your prompt (the thing you type to the right of) might look different than mine. Mine looks like this:
[I] ⋊> ~
.- you might have different programs installed than I do (our
git
s might be in different locations), but it's very likely that we both have a program calledwhich
somewhere.
Similarly, I can type which which
to find out what program is run when I type which
:
[I] ⋊> ~ which which
/usr/bin/which
Rather than using the nickname, I can run the which
program by describing the location precicely:
[I] ⋊> ~ /usr/bin/which git
/usr/local/bin/git
I can run the git
program the same way:
[I] ⋊> ~ /usr/local/bin/git --version
git version 2.11.0
You might have noticed that my git
and which
programs are in different locations. How does my shell know where to look when I type a program's name without specifying where to find it?
It looks at a variable called PATH
.
We can inspect the contents of this (or any) variable using the echo
program.
[I] ⋊> ~ echo $PATH
/Users/ajm/bin /Users/ajm/.yarn/bin /usr/local/bin /usr/bin /bin /usr/sbin /sbin /opt/X11/bin
The dollar sign means "not the word PATH, but the value of the variable called PATH
":
[I] ⋊> ~ echo PATH
PATH
It's possible that your shell prints the variable's value differently than mine. Here's what it looks like if I use my copy of Bash:
bash-3.2$ echo $PATH
/Users/ajm/bin:/Users/ajm/.yarn/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin
It's extremely unlikely that your PATH
variable has the same value as mine. (Your initials aren't ajm, are they?), but our shells follow the same procedure when they need to locate a named program:
procedure for locating a named program
- dereference (find the value of) the $PATH variable
- check for a file with the given name in the first location listed in the value of $PATH
- If there is one, that's the program! Execute it and stop here!
- check for a file with the given name in the next location listed in the value of $PATH
- If there is one, that's the program! Execute it and stop here!
- repeat from step 4 until there are no locations left.
We looked at the program called git
on my machine at /usr/local/bin/git
earlier. I also have program called git
located at /usr/bin/git
. What if I want to run that?
/usr/local/bin
appears before /usr/bin
in the value of the PATH
variable, so according to the procedure for locating a named program, if I just type git
I'll always get the one at /usr/local/bin/git
.
If I want to run the program located at /usr/bin/git
, I can do so using that precise path:
[I] ⋊> ~ /usr/bin/git --version
git version 2.10.1 (Apple Git-78)
Now let's say I want to add a new directory, /Users/ajm/my-programs
to my PATH. In my shell, Fish, I can do so with the program set
[I] ⋊> ~ set PATH $PATH /Users/ajm/my-programs
[I] ⋊> ~ echo $PATH
/Users/ajm/bin /Users/ajm/.yarn/bin /usr/local/bin /usr/bin /bin /usr/sbin /sbin /opt/X11/bin /Users/ajm/my-programs/
That means, define PATH
's value to be its current value, then /Users/ajm/my-programs
In bash, that's like this:
bash-3.2$ PATH=$PATH:/Users/ajm/my-programs
bash-3.2$ echo $PATH
/Users/ajm/bin:/Users/ajm/.yarn/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Users/ajm/my-programs
But, variable assignment in the shell is only temporary. If I begin a new Fish or Bash session, my PATH won't be set anymore.
In most shells, if you have a file at a particular path, it will execute the contents of that file at the beginning of every session. So, if we set the PATH
variable in this file, it will persist.
In fish, one such path is ~/.config/fish/config.fish
. I can add that set command to it with my favorite text editor, or straight from my shell:
[I] ⋊> ~ echo "set PATH \$PATH /Users/ajm/my-programs" >> ~/.config/fish/config.fish
The \
before PATH means "not the value of the variable PATH
, literally a dollar sign"
In Bash, a path to a script which is executed at the beginning of every session is ~/.bashrc
:
bash-3.2$ echo "PATH=\$PATH:/Users/ajm/my-programs
Of course, changing that file won't affect your current session.