2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「PATHを通す」ってどういう意味?コマンドが動く仕組みから手順までを解説

Posted at

はじめに

よく聞く言葉、「PATHを通す」 について調べたので記事としてまとめていこうと思います。

本記事では、 PATHを通す方法とその前提としてコマンドとは何者か? について整理します。

目次

コマンドってそもそも何?

ターミナルで cdlsrails ~docker ~と入力すると、なぜ動作するのでしょうか?

それは、シェルがその名前に対応する「実行ファイル」を探して見つけてくれているから です。

PATHとは?

PATH は、シェルがコマンドを探すための「ディレクトリ一覧」 を表す環境変数です。

PATHの中身を確認するとこんな感じで出てきます。

echo $PATH # $は変数の中身を見るための記号です

/home/shoya/.rbenv/shims:/home/shoya/.rbenv/bin:/home/shoya/.rbenv/shims:/home/shoya/.rbenv/bin:/home/shoya/hello:/home/shoya/.rbenv/shims:/home/shoya/.rbenv/bin:/home/shoya/hello:/home/shoya/.rbenv/shims:/home/shoya/.rbenv/bin:/home/shoya/hello:/home/shoya/.rbenv/shims:/home/shoya/.rbenv/bin:/home/shoya/hello:/home/shoya/.rbenv/shims:/home/shoya/.rbenv/bin:/home/shoya/hello:/home/shoya/.rbenv/shims:/home/shoya/.rbenv/bin:/home/shoya/.rbenv/shims:/home/shoya/.rbenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/wsl/lib:/mnt/c/WINDOWS/system32:/mnt/c/WINDOWS:/mnt/c/WINDOWS/System32/Wbem:/mnt/c/WINDOWS/System32/WindowsPowerShell/v1.0/:/mnt/c/WINDOWS/System32/OpenSSH/:/mnt/c/Program Files/Git/cmd:/mnt/c/Ruby32-x64/bin:/mnt/c/Program Files/PostgreSQL/13/bin:/mnt/c/Program Files/nodejs/:/mnt/c/Users/miyas/AppData/Local/Programs/cursor/resources/app/bin:/mnt/c/Ruby32-x64/bin:/mnt/c/Users/miyas/AppData/Local/Programs/Python/Python312/Scripts/:/mnt/c/Users/miyas/AppData/Local/Programs/Python/Python312/:/mnt/c/Users/miyas/AppData/Local/Programs/Python/Launcher/:/mnt/c/Users/miyas/AppData/Local/Microsoft/WindowsApps:/mnt/c/Users/miyas/AppData/Local/Programs/Microsoft VS Code/bin:/mnt/c/Users/miyas/AppData/Local/GitHubDesktop/bin:/mnt/c/Program Files/PostgreSQL/14/bin:/mnt/c/Program Files/PostgreSQL/16/bin:/mnt/c/Users/miyas/AppData/Roaming/npm:/mnt/c/Users/miyas/AppData/Local/Programs/cursor/resources/app/bin:/mnt/c/Users/miyas/AppData/Roaming/Cursor/User/globalStorage/github.copilot-chat/debugCommand:/snap/bin

PATHの中には、コロン(:)で区切られたディレクトリのリストが表示されていて、左から順にコマンドを探していきます。

:で区切られているのですが、見ずらいので改行してみました。

$ echo $PATH | tr ':' '\n'

/home/shoya/.rbenv/shims
/home/shoya/.rbenv/bin
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/usr/lib/wsl/lib
/mnt/c/WINDOWS/system32
/mnt/c/WINDOWS
/mnt/c/WINDOWS/System32/Wbem
/mnt/c/WINDOWS/System32/WindowsPowerShell/v1.0/
/mnt/c/WINDOWS/System32/OpenSSH/
/mnt/c/Program Files/Git/cmd
/mnt/c/Ruby32-x64/bin
/mnt/c/Program Files/PostgreSQL/13/bin
/mnt/c/Program Files/nodejs/
/mnt/c/Users/miyas/AppData/Local/Programs/cursor/resources/app/bin
/mnt/c/Users/miyas/AppData/Local/Programs/Python/Python312/Scripts/
/mnt/c/Users/miyas/AppData/Local/Programs/Python/Python312/
/mnt/c/Users/miyas/AppData/Local/Programs/Python/Launcher/
/mnt/c/Users/miyas/AppData/Local/Microsoft/WindowsApps
/mnt/c/Users/miyas/AppData/Local/Programs/Microsoft VS Code/bin
/mnt/c/Users/miyas/AppData/Local/GitHubDesktop/bin
/mnt/c/Program Files/PostgreSQL/14/bin
/mnt/c/Program Files/PostgreSQL/16/bin
/mnt/c/Users/miyas/AppData/Roaming/npm
/mnt/c/Users/miyas/AppData/Roaming/Cursor/User/globalStorage/github.copilot-chat/debugCommand
/snap/bin

だいぶ見やすくなりました。確かにPATHの中にたくさんのディレクトリがリストアップされていたようです。このリストの中から上から順にコマンドがあるか探しているみたいです。

例えば、ターミナルでlsコマンドを打つと以下のような流れで探索します。

  1. /home/shoya/.rbenv/shims/ls ← ここにファイルある?
  2. /home/shoya/.rbenv/bin ←ここは?を続けていって、
  3. /usr/bin/ls ← ここにあるみたい。これを使おう!
  4. /bin/ls ← もう見つかったから見に行かない

その証拠に自分で適当に考えた架空のコマンドを打ってみると、少し反応までラグがありました。しばらく探しに行ってくれていたみたいです。

image.png

なんかいろんなお返事が返ってきました。

じゃあ全部のコマンドがこのようにPATHの中を探しに行っているかというと、NOです。

コマンドには種類があるみたいです。以下見ていきましょう。

コマンドの「種類」は4種類ある

シェルにおいて、コマンドの種類には以下の4種類があります

種類 説明
ビルトイン シェルが内部的に持っている命令で、外部ファイルを呼び出す必要がない。 cd, exit
エイリアス 別名をつけて実際のコマンドを短縮化 alias gs='git status'
関数 複数の処理をまとめたシェル関数 myfunc() { echo "hi"; }
外部コマンド PATH上にある実行ファイル ls, git, node ,rails

もう少し詳しく確認しておきましょう

エイリアス(alias)

あるコマンドに別名をつけたもの。コマンド入力を別の形に変換してから実行されます。

よく使うコマンドを短縮するのに便利で、

シェル起動時に .bashrc.zshrc によって定義されます。←ここ重要な部分だと思います。

外部コマンド

シェルが PATH 上で探して見つけた実行ファイル(実行可能なファイル)

実際に lsgit などの 実行ファイル本体
whichcommand -v でパスが返ってくるものは外部コマンドです

which rails
/home/shoya/.rbenv/shims/rails

which git
/usr/bin/git

which ls
/usr/bin/ls

which cd
結果なし

コマンドの種類を確認するには type コマンドが便利です。

type cd
# cd is a shell builtin

type ls
# ls is /bin/ls

type gs
# gs is aliased to `git status`

実行ファイルにも種類がある

先ほど実行ファイルについて軽く触れましたが、もう少し詳しくみてみます。実行ファイルとはコンピュータが直接実行できるファイルのことで、大きく分けて2種類あるようです。

  1. バイナリ実行ファイル
  2. スクリプト実行ファイル

1. バイナリ実行ファイル

  • C言語などでビルドされた機械語の実行ファイル(例:/usr/bin/ls)
  • CPUが直接理解して実行できる形式

2. スクリプト実行ファイル

  • シェルスクリプトやPython, Ruby などのスクリプト言語で書いた「人が読めるテキストファイル」
  • 1行目にシバン(shebang、#!/bin/bashなど)があり、シェルが解釈して実行

自分で作るなら基本は「スクリプトファイル」

「バイナリ実行ファイル」はC言語などでコンパイルして作られたもので、基本は外部アプリやOS組み込みのものって感じですね。

スクリプトファイルにシバンをつけてあげることで、実行ファイルの中身をコンピュータが読むときに

  • どの言語で実行するべきかを明確に指定できる
  • 「バイナリかテキストか」という判断による実行エラーを防ぐことができる

#!/bin/bash  

echo "#!はシバンといって、今回はこのechoコマンドを「bashで実行するんだよ」と教えてくれてます"

それではそろそろPATHを通す方法を見ていきます。

PATHを通すとは?

ここまで、PATHとコマンド、実行ファイルについて確認してきましたが、PATHを通すとはどういうことなのでしょうか?実際に手を動かして確認してみました。

たとえば、~/scripts/hello というスクリプトファイル(実行ファイル)を自作してコマンドにしたい場合

① スクリプトを作る

# ~/scripts/helloファイルの中身

#!/bin/bash 
echo "こんにちは!"

image.png

② 実行権限をつける

chmod +x ~/scripts/hello
# 読み込み権限(r)・書き込み権限(w)・実行権限(x)があった中のxですね。

③ PATHに登録する


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

# ~/.bashrc または ~/.zshrcの中に記入します。
# 直接ターミナルに打ち込むこともできますが、一回きりになってしまいます。理由はのちほど。

④sourceで変更を反映させる

source ~/.bashrc

これでどこにいても hello と打つだけで「こんにちは!」とあいさつできます。良かったですね。

image.png

無事挨拶できました🙌

では途中で出てきた.bashrc / .zshrcsourceとは何なのでしょうか?


.bashrc / .zshrc って何?

  • .bashrc(bash)や .zshrc(zsh)は、シェル起動時に読み込まれる設定ファイル
  • エイリアスや環境変数(PATH)を毎回自動で設定するために使います
# .bashrc の中身にこれを書くと、パスを登録できます。
export PATH="$HOME/scripts:$PATH"

exportって何?

変数を環境変数として使えるようにするためのコマンドです。

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

これで$HOME/scripts/home/shoya/scripts) をPATHの先頭に追加して、PATHをシェル全体に知らせています。

cursor ~/.bashrcだけで別の記事を書く

その後、変更を反映するには:

source ~/.bashrc

sourceって何?

source は、「スクリプトの中身を今のシェルに読み込む」という意味です。

とすると、.bashrc に書かれた設定をすぐに反映できます。

sourceしないと現在のターミナル上では反映されません。

しかし別のターミナルをこのタイミングで開くと反映されています。どういうことでしょうか?

環境変数と設定ファイルの読み込み

ちょっとターミナルを擬人化するとわかりやすかったので最後に紹介していきます。

image.png

  • ターミナルを開くと、新しいターミナルくんが誕生する
  • ターミナル君は生まれた瞬間に ノート(.bashrcまたは .zshrc)を読んで、中身をぜんぶ暗記する
  • でもその後に .bashrc を書き換えても、ターミナルくんは気づかない
  • だから、「もう一回ノート読んで!」とお願いするコマンドがsource ~/.bashrc
  • 新しく開いたターミナルくんは「最初に.bashrc.zshrcを読み込む」から、すでに最新の状態を知って生まれてくる。

sourceではなく、ターミナルにexportコマンドを直接打ち込んだ場合の環境変数のスコープはこんな感じです

# ターミナルくんAで export した場合

[ターミナルくんA]
├─ export NAME="DECOPIN"  # ホワイトボードに書いた
├─ bashくん(子)      # NAME を知ってる!
├─ pythonくん(子)    # 知ってる!
├─ rubyくん()        # 知ってる!
└─ lsくん(子)        # 知ってる!

[ターミナルくんB](別のタブ)
└─ NAME ?            # 知らない

しかし、最初にターミナルは最初にbashrcまたは .zshrcというノートを読み込んでいるので、

# .bashrcに書いておけば、
# .bashrcの中身
export NAME="DECOPIN"

# ターミナルくんA
$ echo $NAME
DECOPIN

├─ bashくん(子)      # NAME を知ってる!
├─ pythonくん(子)    # NAME を知ってる!
├─ rubyくん()        # NAME を知ってる!
└─ lsくん(子)        # 知ってる!

# ターミナルくんB(別タブで生まれた)
$ echo $NAME
DECOPIN

├─ bashくん(子)      # NAME を知ってる!
├─ pythonくん(子)    # NAME を知ってる!
├─ rubyくん()        # NAME を知ってる!
└─ lsくん(子)        # 知ってる!

# ノート(.bashrc)に書いておけば、
# みんな同じ初期知識をもって生まれてくる!

おわりに

だいぶ長くなりましたが最後までお読みいただきありがとうございました。

なかなか普段使うコマンドを意識することはないですが、なんで動いているのか?を意識してみるとかなり学びが深いなと思いました。

最後にまとめの表を置いておきます。

概念 意味
PATH シェルがコマンドを探す場所の一覧
コマンドの種類 ビルトイン / エイリアス / 関数 / 外部コマンド
$ 変数の中身を参照
export 環境変数を登録する
source 設定ファイルを今のシェルに読み込む
.bashrc / .zshrc シェルの起動時に読み込まれる設定ファイル。PATHやエイリアスを永続化するのに使う
2
2
1

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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?