32
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

本記事のサンプルコードの環境はZshを用いています。

$ node
zsh: command not found: node

Node.js をインストールしたはずなのに、node が使えないなあ。
このようなエラーに遭遇し、ネットで調べたところ「パスを通してください」という謎の助言を見かけたことがある人は少なくないと思います。

「パスを通す」ってなに?

結論ですが、「パスを通す」とは環境変数 PATH にディレクトリを追加することです。

なぜそんなことをする必要があるのでしょうか?

コマンド実行の仕組み

例えば lspython のようなコマンドを実行すると、シェルはそれに対応する 実行ファイル(プログラム) を探しにいきます。

そもそもプログラムを実行するだけなので、もちろん 絶対パスで直接実行することも可能 です。

$ /bin/ls
$ /opt/homebrew/bin/python # brewでインストールした場合

ですが、毎回このようにフルパスで書くのは面倒くさいですよね。

環境変数PATHとは

そこで PATH が活躍します。

PATH は、シェルがコマンドを探す際に「このフォルダの中を探してくださいね」と決めておくディレクトリの一覧です。
実際に中身を覗いてみましょう。

$ echo $PATH
/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin # あくまで一例です。通常ここまで少ないことはないと思います。

: で区切られて複数のディレクトリのパスが並んでいます。
上記の場合、これらがどのように機能しているのでしょうか。

例えば python と入力されると、シェルは次のような順序でプログラムの本体を探しに行きます。

  1. /opt/homebrew/bin/ にあるか?
  2. なければ /usr/local/bin/ は?
  3. それでもなければ /usr/bin/ と、順番に確認

そして、 最初に見つけたプログラムを実行 します。

ちなみに、コマンドの実行ファイルがどこにあるのか確認したい場合は、以下のように確かめることができます。(パスが通っていれば見つかります)

$ which python
/opt/homebrew/bin/python

上記の場合、/opt/homebrew/bin/pythonpythonの実行ファイルが設置されていることがわかります。
もちろん、これは絶対パスの指定で実行することも可能です。

PATH以外は探さない

重要なのは、PATH に登録された場所以外は探してくれないということです。

以下のケースを考えてみます。

$ echo $PATH
/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin

$ ls ~/.scripts
dairy_script.sh

実行したいプログラムが ~/.scripts/dairy_script.sh だとします。
しかしながら、 $PATH には /opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin しか登録されていません。
プログラムを探す場所として .scripts ディレクトリが登録されていないため、 dairy_script.sh と実行しても当然プログラムが見つからずエラーになります。

$ dairy_script.sh
zsh: command not found: dairy_script.sh

PATHを追加する意味

「パスを通す」とは

プログラムが存在する場所を PATH に追加して、シェルが探せるようにすること

なわけですね。

ですので、パスを通してプログラムの場所を探せるようにしてあげれば、どこからでも簡単に呼び出すことが可能になります。

$ export PATH="$HOME/Desktop/scripts:$PATH"

$ dairy_scripts.sh

export の落とし穴

先ほど紹介したように、 exportPATH を更新すればどこからでも呼び出せるようになりますが、実はこれは 一時的にしか動作しません。

ターミナルを閉じるとリセットされる

export コマンドで設定した環境変数の変更は、ターミナルを閉じたり再起動すると、綺麗さっぱり消滅します。
ターミナルを起動するたびに毎回手動で export するのは現実的ではないですよね。

毎回設定するには?

その手間を省くためには、 シェルが起動時に読み込む設定ファイルに PATH の追加を書いておく のが一般的です。

使用しているシェルによって、読み込まれる設定ファイルは異なります。(基本的に役割は同じです)

シェル 設定ファイル
Bash ~/.bash_profile, ~/.bashrc
Zsh ~/.zshrc
Fish ~/.config/fish/config.fish

たとえば zsh を使っている場合、 ~/.zshrc に以下のように書いておけば、起動するたびに設定してある内容が反映されます。

# ~/.zshrc
export PATH="$HOME/Desktop/scripts:$PATH"

プログラムを探す順番

補足ですが、シェルはコマンドを実行する際に、 PATH に登録されたディレクトリを 左から順番に 探していきます。

たとえば以下のような PATH が設定されているとします。

$ echo $PATH
/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin

先ほども少し触れましたが、例えばこの状態で python を実行すると、次のような順番でプログラムを探します。

  1. /opt/homebrew/bin/python を確認
  2. 見つからなければ /usr/local/bin/python を確認
  3. 見つからなければ /usr/bin/python を確認
  4. 見つからなければ /bin/python を確認
  5. この中で最初に見つかったものを実行する
  6. 全てのディレクトリで見つからなければ command not found になる

したがって /usr/bin/python/opt/homebrew/bin/python の両方に存在していた場合、先に見つかる /opt/homebrew/bin/python の方が実行されるわけです。

(発展)ビルトインコマンドと外部コマンド

コマンドは PATH の中から探し、実行ファイルが見つかったものが実行されるという話をしました。

ですが、実際はすべてのコマンドが PATH から探されているわけではありません。
普段利用する cdpwd など、パスを通した覚えはありませんよね。

実は、コマンドには 「ビルトインコマンド」と「外部コマンド」 の 2 種類があり、 PATH から探されるのは外部コマンドだけ なんです。

ビルトインコマンドとは?

ビルトインコマンドは、 シェルにあらかじめ組み込まれているコマンド です。
外部にプログラムが存在しているわけではなく、シェルの内部で実装されています。
興味があれば、Bash のソースコードを見ていただくと、コマンドがどのように実装されているのかがわかります。

例として、以下のコマンド群はビルトインコマンドです。(一部の抜粋です)

  • cd
  • echo
  • exit

どうやって調べるの?

type でコマンドの種類を判別できます。

$ type cd
cd is a shell builtin

cd がビルトインコマンドであることがわかりますね。

ビルトインコマンドは 外部のプログラムとして存在していないため、PATH の影響を受けません。
「パスを通す」といった操作とは無関係で、何もしていなくとも使えるコマンドというわけです。

外部コマンドとは?

  • ls, node, python, git など
  • 外部に実行ファイルが存在
  • 実行時は PATH を見て探す
$ type node
node is /opt/homebrew/bin/node

こちらはお話している通り、外部にプログラムが置いてありますので、 PATH を通す必要があります。

おわりに

「パスを通す」とはどういうことなのか、色々な角度からお話しました。

これでもう「パスを通してね」と言われても、「はいはい、PATH ね」とすんなり理解できるようになったかと思います。

32
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?