•14 min read

LinuxでPATHにディレクトリを追加する方法(永続的な修正)

LinuxでPATHにディレクトリを追加する方法(永続的な修正)

ツールをインストールして実行したら、command not foundと表示された。バイナリがシステム上のどこかに存在することは分かっている。ls /home/user/.local/bin/my-toolを実行すれば、そこにあるのが見える。しかし、ターミナルはそれを認識しない。

この現象は、私が実際に何が起こっているのかを理解するまでに、少なくとも3回は経験した。解決策は、そのディレクトリをPATH環境変数に追加することだ。

Audio Briefing
0:00 / 0:00
Part of a Series

モダンLinuxとターミナルマスターシリーズ

Part 1 of 4

PATHの実際の仕組み

ターミナルでmy-toolと入力しても、シェルはファイルシステム全体を検索するわけではない。PATH変数内にリストされているディレクトリを、順番に1つずつチェックするだけだ。一致するものが見つかった瞬間に、検索を停止する。

典型的なPATHは次のようになる。

/home/user/.local/bin:/usr/local/bin:/usr/bin:/bin

コロンは区切り文字だ。つまり、シェルはまず/home/user/.local/bin、次に/usr/local/bin、次に/usr/bin、最後に/binを検索する。もしツールが/home/user/.local/binにあり、そのディレクトリがリストに含まれていなければ、シェルはそれを見つけることはない。

聞き覚えがあるだろうか?

現在のPATHを確認するには、以下を実行する。

echo $PATH

これはコロン区切りの文字列を出力する。正直、あまり読みやすいとは言えない。

特定のコマンドが実際にどこから来ているのかを確認するには、以下を実行する。

which <command>

これは、シェルがどの実行可能ファイルに解決し、どのディレクトリでそれを見つけているかを教えてくれる。

Advertisement

ディレクトリを永続的に追加する

ここで人々は迷子になる。一時的なPATHの変更と永続的なPATHの変更がある。私は長い間、これらを混同していた。

一時的とは、ターミナルで直接export PATH="$PATH:/home/user/.local/bin"を実行することを意味する。その場では機能する。しかし、そのターミナルを閉じ、新しいターミナルを開くと、何も変更されていない。

永続的とは、シェルの設定ファイルを編集して、再起動後も変更が残るようにすることを意味する。

編集するファイルは、使用しているシェルによって異なる。

Bash

Linuxでは~/.bashrcを、macOSでは~/.bash_profileを編集する。この行を追加する。

export PATH="$PATH:/home/user/.local/bin"

ファイルを保存し、以下で再読み込みする。

source ~/.bashrc

または、新しいターミナルウィンドウを開くだけでもよい。それも機能する。

Zsh

~/.zshrcを編集する。行は同じだ。

export PATH="$PATH:/home/user/.local/bin"

以下で再読み込みする。

source ~/.zshrc

Fish

Fishは異なる。export構文は使用しない。代わりに、~/.config/fish/config.fishを編集して以下を追加する。

fish_add_path /home/user/.local/bin

私がFishを気に入っている理由はここにある。重複エントリを自動的に防いでくれるのだ。そして、デフォルトでPATHの先頭にパスを追加するため、新しいディレクトリが優先される。これは、ローカルにインストールされたツールをシステムバージョンよりも優先させたい場合に便利だ。

その「export」の技は、そのセッションでしか機能しない

私はこれを苦い経験から学んだ。ターミナルでexport PATH="/some/path:$PATH"を実行し、うまくいったと喜んでウィンドウを閉じ、なぜすべてがリセットされたのか不思議に思ったものだ。設定ファイルに書かれていなければ、永続化しない。常にだ。

私を何度もつまずかせた間違い

何人かのPATHの問題をデバッグするのを手伝った後、私は同じ問題が何度も繰り返されることに気づいた。

間違ったプログラムが使用される

何かをインストールしたのに、なぜ古いバージョンがまだ実行されているのか疑問に思ったことはないだろうか?おそらく、2つのディレクトリに同じ名前のプログラムがあるのだろう。PATHで最初にリストされているものが、常に優先される。which <command>を実行してパスを確認してみよう。期待していたものだろうか?

もしそうでなければ、どこかに重複が隠れている。

権限がすべてをブロックする

これは後から考えれば明らかだが、デバッグに恥ずかしいほど長い時間がかかった。ディレクトリは読み取り可能である必要があり、ファイルには実行権限が必要だ。どちらかが間違っていると、シェルはコマンドが存在しないかのように振る舞う。

修正は簡単だ。

chmod +x /path/to/file

クォーテーションが正気を保つ

PATHの割り当ては常にクォーテーションで囲むこと。これは機能する。

export PATH="$PATH:/home/user/.local/bin"

これは、パスにスペースが含まれている場合にサイレントに壊れる。

export PATH=$PATH:/home/user/.local/bin

エラーメッセージは表示されない。ただ壊れたPATHがあるだけだ。クォーテーションは2文字しかかからない。使うべきだ。

重複エントリが積み重なる

複数の設定ファイルにexport行を追加し続けたり、設定を複数回ソースしたりすると、PATHに同じディレクトリが2回、3回、あるいは5回もリストされることになる。危険ではないが、ごちゃごちゃする。

現在のシェルで重複を見つけるには、以下を実行する。

echo $PATH | tr ':' '\n' | sort | uniq -d

Fishのfish_add_pathはこれを自動的に処理する。BashとZshのユーザーはもっと注意する必要がある。

実際に機能するステップバイステップのワークフロー

この問題に遭遇したときに私が今使っているプロセスを説明しよう。

バイナリが実際にどこにあるかを見つける

正確なパスを知っていれば素晴らしい。そうでなければ、find ~ -name "my-tool" -type f 2>/dev/nullで検索する。これはホームディレクトリで「my-tool」という名前のファイルを検索する。

すでにPATHにあるか確認する

echo $PATH | tr ':' '\n' | grep -x "/path/you/found"を実行する。-xフラグは「正確な行の一致」を意味する。何も表示されなければ、まだそこにはない。

シェル設定に追加する

シェルに適したファイルを開く(echo $SHELLで確認)。適切な行を追加する。bash/zshの場合:export PATH="$PATH:/path/you/found"。fishの場合:fish_add_path /path/you/found。

再読み込みして確認する

source ~/.bashrc(またはそれに相当するもの)を実行する。次にwhich my-toolを実行し、正しい場所を指していることを確認する。

Advertisement

Fishがしっくりくるとき

私は数年前にFishを使い始めたが、その主な理由はPATHの扱い方だった。fish_add_pathビルトインは期待通りの動作をし、重複を追加することはなく、存在しないものを追加しようとすると明確な警告を出してくれる。

これだけのためにシェルを切り替える価値はあったか?まあ、ある程度は。他のQoL(Quality of Life)機能も私をそこに留まらせた。しかし、bashやzshに満足しているなら、切り替える必要はない。設定ファイルにもっと注意を払うだけでよい。

私にとって腑に落ちたメンタルモデル

PATHをチェックポイントの連続だと考えてほしい。コマンドを入力すると、シェルは順番に各チェックポイントをたどっていく。最初の停止は/home/user/.local/bin。2番目の停止は/usr/local/bin。3番目の停止は/usr/bin。必要な実行可能ファイルがある最初のチェックポイントが使用される。

並行して何も起こらない。建物全体を検索することもない。ただリストを順番にたどっていくだけだ。

それが腑に落ちたとき、PATHに関するすべてが私には理解できた。

PATHの順序はあなたが思う以上に重要だ

2つのプログラムが同じ名前を共有している場合、PATHディレクトリのより早い位置にあるものが優先される。システムバージョンではなく、ローカルにインストールされたバージョンを実行したい場合は、PATHの先頭に自分のディレクトリを置く。システムバージョンをデフォルトにしたい場合は、最後に置くか、ローカルディレクトリをまったく追加しない。

クイックリファレンス

シェル設定ファイルコマンド
Bash~/.bashrcexport PATH="$PATH:/new/path"
Zsh~/.zshrcexport PATH="$PATH:/new/path"
Fish~/.config/fish/config.fishfish_add_path /new/path

まとめ

PATHの混乱は、腑に落ちるまでは謎めいて感じる問題の一つだ。チェックポイントの類推を理解すれば、他のすべてがうまくいく。

テキストエディタで~/.bashrc(Bashの場合)または~/.zshrc(Zshの場合)を開き、ファイルの最後にexport PATH="$PATH:/your/directory/path"を追加して保存し、source ~/.bashrcを実行してターミナルセッションを再読み込みします。

コマンドラインで直接export PATH=...を実行すると、現在のシェルプロセスに対してのみ変数が設定されます。将来のすべてのターミナルウィンドウで永続化させるには、export行をシェル設定ファイル(~/.bashrcまたは~/.zshrc)に追加する必要があります。

同じツールのシステムバージョンをカスタムバイナリで上書きしたい場合は、先頭に追加します(export PATH="/custom/bin:$PATH")。システムバイナリに実行優先順位を維持させたい場合は、末尾に追加します(export PATH="$PATH:/custom/bin")。


こちらもおすすめ

Share this article:

Stay Updated

Get the latest posts delivered straight to your inbox.

Free Developer Utilities

Free In-Browser Developer Tools

Clean AI CLI logs, build cron expressions, decode JWTs, and calculate chmod permissions offline.

Explore Tools
Advertisement
ターミナルプログラムの暗黙のルール
terminal

ターミナルプログラムの暗黙のルール

なぜ「q」でほとんどのものが終了し、Ctrl-Cがユニバーサルなkill switchになったのか、そしてコマンドラインを使い慣れたものにするPOSIXの幽霊について解説します。

Read more