はじめに
Linuxをやっていると必ず耳にするであろう「PATHを通す」という言葉。
これ、結構初心者泣かせのワードではないでしょうか。
書き方がイマイチわからないとか、そもそも何のためにこの作業をするのかとか、
なかなか最初のうちは理解しにくいかと思います。
でも、大丈夫です。すぐにわかるようになりますので!
本記事が、そんな皆さんの理解の助けになれば幸いです。
注意事項
本記事では、なるべくわかりやすくなるように、できるだけ難しい言葉を避けて記述を行なっています。
言葉の正確さよりも理解しやすさの方を優先していますので、一部用語の正確性を欠いた部分があるかもしれません。
あらかじめご了承ください。
なお、シェルは特に記載がない限りbashを利用して説明しています。
何でPATHを通すの?
そもそも論として、なぜPATHを通すのでしょうか。
答えは簡単です。
実行可能なプログラムの場所をシェルに教えてあげるため
です。これをもう少し噛み砕きましょう。
まずはシェルに怒られてみる
今、以下のようにカレントディレクトリに hoge.bash というシェルスクリプトがあるとします。
$ pwd
/opt/hoge/bin
$ ls
hoge.bash
このシェルスクリプトを実行したいと思います。
そこで、以下のように打ちました。すると、シェルからエラーが返ってきてしまいました。
$ hoge.bash
-bash: hoge.bash: command not found
コマンドが見つからないよ!と怒られているんですね。
シェルスクリプトを「コマンド」というのが正しいのかはさておき、
hoge.bash は間違いなく存在しているのに、「not found」というのはおかしい!と思うかもしれません。
この挙動を理解するには、シェルのコマンド実行の流れを理解する必要があります。
シェルのコマンド実行までの大まかな流れを掴む
まず、我々が普段使っているlsなどのコマンドですが、実はその正体は全てファイルです。
シェルがやっているのは、lsと打たれた瞬間にそのlsを実行するためのファイルをどこかから探すということなんです。
(実際にはシェルが自身の分身を作って、その分身がコマンドに置き換わって実行されるのですが、ここでは詳細は無視します。)
しれっと「どこかから探す」と書きましたが、では一体どこから探すのでしょう?
システム上はファイルの海です。無数のファイルが存在しています。
いくらCPUの処理速度が飛躍的に向上しているとはいえ、
毎回何の手がかりもなくシステムにある全てのファイルを確認していては、あまりに効率が悪いですね。
そこで偉い人たちは考えました。
コマンドをどこかのディレクトリに集約させて、その中だけを探すようにすればいいんじゃない?
で、そのコマンドを置いているディレクトリの場所だけをシェルに教えておけば大丈夫だよね!
と。
この仕組みのおかげで、シェルはlsなどと打たれた時、特定のディレクトリだけを探しに行くだけで済みます。
そのディレクトリでファイルが見つかればそれを実行。なければ command not found というエラーを返してくるというわけです。
そしてその、コマンドを置いているディレクトリをシェルに伝える手段こそ、PATHなのです!
なぜ怒られたかを振り返る
大まかな流れが理解できたところで、先程の実行結果をもう一度振り返ってみましょう。
$ pwd
/opt/hoge/bin
$ ls
hoge.bash
$ hoge.bash
-bash: hoge.bash: command not found
hoge.bash と打った時、ファイル名しかシェルに伝わっていません。
よって、シェルはPATHに記載されたディレクトリの中に hoge.bash が存在するかを確かめに行きました。
では、その時の環境変数PATHの値はどうなっていたでしょうか。確認してみます。
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
hoge.bash が存在していたディレクトリは /opt/hoge/bin です。
このディレクトリはPATHには記載されていません。
だからシェルは「せっかくPATHに書かれたディレクトリを探しに行ったのに無かったよ!」と文句をつけてきたわけですね。
分かったところで、PATHを通してみる
ここまで理解できれば、第一関門は突破です。
PATHを通すことによって、hoge.bash を探索可能にしてみましょう。
このファイルのあるディレクトリは /opt/hoge/bin なので、以下のような記載になります。

なにやら覚えにくい形をしていますね...
このへんてこりんな書き方こそが、初心者をつまづかせる第二関門と言っていいでしょう。
ですが大丈夫です。なぜこのように書くのかを理解すれば、必ず書けるようになります。
どうやってPATHを記述するの?
まずはPATHがどのように書かれているのかを見てみましょう。
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
スラッシュやらコロンやらの記号が多めの出力ですが、ここからわかるのは以下の内容です。
各々のディレクトリをコロン区切りで記載する
/usr/local/bin や /bin というのはディレクトリで、それがコロン区切りで列挙されているだけです。
これが分かれば、ほとんど記載できたも同然です。
まずは愚直な書き方で
(1)は先程のPATHの出力をそのまま記載したものです。
そして(2)は、「各々のディレクトリをコロン区切りで記載する」という事実を基に、(1)の後ろに :/opt/hoge/bin を付加し、PATHに代入したものです。
実は、この書き方でもPATHはきちんと設定されます。文法的に何も問題はありません。
問題はないのですが、あまりに長ったらしいと思いませんか?
いちいち全部書かなくてはいけないとなると面倒ですし、なにより一番最悪なのが、
どこかで記載を間違えてPATHがうまく通らなくなり、コマンドが実行できなくなることです。
例えば、/usr/bin と書くところを /ust/bin としてしまうと、/usr/bin 以下のコマンドが全て実行できなくなってしまいます。
今度はスマートに
そもそも、上の図の(2)は(1)で見た出力をそのまま流用しているため、以下の図の赤い部分のような関係になるのは明白です。

したがって、(2)は(3)のように置き換えられます。
かなりすっきりしましたね!
ここで、「両辺にPATHがあるが、これはいいのか?」と思われる方もおられるかと思います。
ですが、変数に代入する際にはまず右辺が先に評価されてから左辺に入れられるので、
(3)では右辺の$PATH が先に展開されてから左辺に代入されます。
よって、(3)も最終的には(2)の形に化けてから代入されるのです。
(3)のような記述だと記述量が一気に減りますし、
元々PATHが設定されていたディレクトリを直接書く必要がないので、
今まで実行できていたコマンドが実行できなくなるという事態を避けることもできます。
最後に一つ加えて完成
(3)の記載のままだと、その変数PATHは「シェル変数」となってしまいます。
PATHは環境変数として設定したいので、そのためにexportする必要があります。(シェル変数と環境変数の違いは割愛)
よって、以下のように記述することで全体が完成することになります。
$ export PATH=$PATH:/opt/hoge/bin
実行してみる
PATHを通したので、実行してみます。
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/hoge/bin
$ pwd
/opt/hoge/bin
$ ls
hoge.bash
$ hoge.bash
This script just echoes 'hoge'
hoge
今度はちゃんと実行されましたね!
まとめ
いかがでしたか。
環境変数PATHとは、実行可能なプログラムをの場所をシェルに教えるための手段であるという点と、
その書き方について説明しましたが、本記事を読み終えて納得していただけたのなら本望です。
一見すると難しいPATHの設定も、その本質を理解するだけで簡単に設定できるようになります。
ここまででまだ理解できたかわからないという方は、納得いくまで理解を深めていただくのがよいと思います。
