16
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?

More than 3 years have passed since last update.

「PATHを通す」とどうなるのか【プログラミング初心者】

Last updated at Posted at 2020-02-23

環境構築をすることが多くなり、PATHを通す機会が増えました。
今までは書いてある通りのコードを意味も理解せず追加してPATHを通していましたが、そのコードの意味をちゃんと理解して、PATHを通すとは何をしているのかを知りたいと思い調べました。

この記事のゴール
:triangular_flag_on_post: PATHを通すとどうなるのか理解する。
:triangular_flag_on_post: 通したPATHを読めるようになる。
(今回はnodenvを使用する際に通すPATH export PATH="$HOME/.nodenv/bin:$PATH"の意味を理解したいと思います)

1.PATHを通すとどうなるのか

そもそもパスとは何か

「PATHを通す」を理解する前に、そもそもパスとは何かを調べます。

パス(path)とは…

コンピュータ内で特定の資源の所在を表す文字列のことをパスという。
ストレージ(外部記憶装置)内でファイルやディレクトリ(フォルダ)の位置を表すのに用いられるが、他の用途でも使われる。
パスとは - IT用語辞典 e-Words より

特定のディレクトリの場所を示す、道順のようなものです。
ex:Desktopのパス
/Users/mac(※ユーザ名)/Desktop

:four_leaf_clover: メモ知識:pathは日本語で「経路」という意味を持つ

環境変数のPATH

「PATHを通すとどうなるか」を知るには、環境変数の1つであるPATHの理解が重要になります。
環境変数とはなにか、というところから調べてみます。

環境変数とは

OSが提供する機能の1つです。

環境変数とは、OSが設定値などを永続的に保存し、利用者や実行されるプログラムから設定・参照できるようにしたもの。プログラムの実行時などに必要となる、利用者やコンピュータごとに内容が異なる設定値などを記録するために用いられる。
環境変数とは - IT用語辞典 e-Words より

環境変数は以下のコマンドで確認できます。
$ printenv

出力結果

bash

mac$ printenv

TERM_PROGRAM=iTerm.app
SHELL=/bin/bash
TERM=xterm-256color
USER=mac
...省略
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
...省略
HOME=/Users/mac
LOGNAME=mac
SECURITYSESSIONID=186a8
_=/usr/bin/printenv

TERM_PROGRAMSHELLTERMといったワードが全て環境変数と呼ばれるものです。

それぞれの変数に対して値が入っています。
TERM_PROGRAM=iTerm.app
SHELL=/bin/bash

環境変数一覧の中に**PATH**があることが確認できます。

PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

値は/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbinですが、は区切りの意味なので、区切りで改行すると以下の値が入っていることが分かります。


/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

# 区切り:で改行
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin

:four_leaf_clover: メモ知識:シェルやターミナル上で環境変数を使用するときは、**環境変数の前に**をつけることで使用できる。

bash
# 環境変数PATHの内容を表示する
$echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

環境変数PATHの役割

PATHは環境変数の1つであり、/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbinといった値が入っていることが分かりました。(通しているPATHによって値は異なります)

では、この環境変数PATHに値を入れることで何が起こるのでしょうか?

PATHは、コマンド実行ファイルが保存されているディレクトリの場所を設定する変数で、PATHに登録されたディレクトリにあるコマンドは、コマンド名のみで実行できるようになります。

:four_leaf_clover: メモ知識:コマンド … シェルなどが解釈して実行する、システムへの指示

ターミナルでコマンド実行ファイルのパスを入力すると、コマンドを実行します。
例えば、printenvコマンドは/usr/bin/printenvと入力することで実行できます。

bash
$which printenv
/usr/bin/printenv

# printenvコマンドは/usr/binの中にあるため/usr/bin/printenvで実行できる。
$/usr/bin/printenv
TERM_PROGRAM=iTerm.app
SHELL=/bin/bash
TERM=xterm-256color
・・・省略

しかし、$printenvのみでも同じ出力結果を得られます

bash

$printenv
TERM_PROGRAM=iTerm.app
SHELL=/bin/bash
TERM=xterm-256color
・・・省略

なぜ/usr/bin/printenvと書かずにprintenvだけでも実行できるのでしょうか?
それは、**環境変数PATHに/usr/binがある(=パスが通っている)**からなんです。


PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

# 区切り:で改行
/usr/local/bin
/usr/bin
# ↑これ
/bin     
/usr/sbin
/sbin

シェルはコマンドがパスの指定なし(/usr/bin/printenvではなくprintenv)で入力された時、環境変数PATHに設定してあるディレクトリへコマンド実行ファイルを探しに行き、同じ名前のファイルがあればそれを実行します。

:warning: 正確には、パスなしでコマンドを実行する際、シェルは「エイリアス」→「ビルトインコマンド」→「環境変数PATHに登録されているディレクトリにある実行コマンド」の順番で探し、最初に見つけたものを実行します。
PATHを理解して、コマンドの在りかを探してみよう

:bulb: $printenvを実行した時の流れ


# 1. printenvコマンドを実行
$printenv

# 2. エイリアス、ビルトインコマンドを確認。該当するコマンドがない場合は環境変数PATHを確認します。

# 3. 環境PATHを確認
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

# 先頭に記述されているディレクトリから順番にそのディレクトリ下にprintenvの実行ファイルがあるかを確認していきます
/usr/local/bin
 ↓
/usr/bin
 ↓
/bin
 ↓     
/usr/sbin
 ↓
/sbin

# 4. /usr/local/binの下にprintenvの実行ファイルがあるか確認します。存在しない場合は、次に記述されているディレクトリを確認します
/usr/local/bin # printenvの実行ファイルなし
 ↓
/usr/bin

# 5. /usr/binの下にprintenvの実行ファイルがあるか確認し、printenvコマンドが存在することを確認
/usr/binにprintenvの実行ファイルがある!

# 6. /usr/binの下にあるprintenv実行ファイルが実行されます
/usr/bin/printenvの実行

# 出力結果
TERM_PROGRAM=iTerm.app
SHELL=/bin/bash
TERM=xterm-256color
・・・省略

このような流れにより、コマンド実行ファイルが入っているディレクトリのパス環境変数PATHに追加する(=PATHを通す)ことで、コマンド名だけで実行できるようになるのです。

まとめ

:triangular_flag_on_post: PATHを通すとどうなるのか
PATHを通したディレクトリ内にあるコマンド実行ファイルを、コマンド名のみで実行できるようになる。逆に、PATHを通さないとコマンド名のみでは実行できない。

寄り道① PATHが通ってない時のエラー

PATHが通っていないのにコマンド名のみで実行すると、command not foundといわれます。このエラーがでたときはPATHがちゃんと通っているか確認してみましょう。

bash
#nodenvコマンドがあるディレクトリのPATHを通さずに$nodenvを実行してみる

#ファイルパスを指定して実行
$/Users/mac/.nodenv/bin/nodenv -v
nodenv 1.3.1+11.5024679

#コマンド名のみで実行
$nodenv -v
-bash: nodenv: command not found
#PATHが通っていないためコマンドを見つけられない

寄り道② /usr/binにあるコマンド実行ファイルをみてみる

/usr/binディレクトリには、printenvコマンドの他にもたくさんのコマンド実行ファイルが入っています。
どんなコマンドが入っているのでしょうか?ターミナル上で確認してみようと思います。

bash
# /usr/binの中身を表示
$ls /usr/bin
2to3-@                              machine*
2to3-2.7@                           mail*
AssetCacheLocatorUtil*              mailq@
AssetCacheManagerUtil*              mailx*
AssetCacheTetheratorUtil*           make*
BuildStrings*                       makeinfo*
CpMac*                              malloc_history*
DeRez*                              man*
...省略

みたことのないコマンドがたくさんあります。/usr/binのPATHは通っているので、ここにあるコマンドはコマンド名だけで実行することができます
/usr/binの他にも、今PATHが通っているディレクトリの中身を確認するのも面白いと思います。

2.通したPATHを読む

PATHを通すとどうなるか理解できたところで、実際にPATHを通すコードを読んでみたいと思います。
PATHの通し方については詳しく説明しないので、知りたい方は以下の記事をぜひ参考にしてみてください。
MacでPATHを通す

今回はnodenvのPATHを通すコードを読んでいきます

export PATH="$HOME/.nodenv/bin:$PATH"

nodenvの環境構築は以下の記事を参考にして行いました。
nodenv を使って Mac に Node.js の環境を構築する

ではexportから読んでいきます。

export 〜で環境変数を変更します。
:four_leaf_clover: メモ知識:export … 環境変数やシェル変数を設定するコマンド

PATH=〜PATH変数値を代入しています。
代入する値は"$HOME/.nodenv/bin:$PATH"です。

シェルは$環境変数を使用すると、環境変数を展開することができます。

bash
# 環境変数HOMEの値を確認
$echo $HOME
/Users/mac

# 環境変数PATHの値を確認
$echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

# bash_prifileに export PATH="$HOME/.nodenv/bin:$PATH" を追加

#.bash_profileの更新
$source ~/.bash_profile

# 環境変数PATHの確認
$echo $PATH
PATH=/Users/mac/.nodenv/bin/nodenv:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

$HOME と $PATH が展開されている!!

詳しく内容を読み解いていきます。
$HOME/.nodenv/bin:$PATH$HOMEは**/Users/mac**、$PATHは**/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin**になっています。

そのため、$HOME/.nodenv/binは**/Users/mac/.nodenv/bin/nodenv**となります。

で区切りを表し、そのあとに$PATHがきているので、/Users/mac/.nodenv/bin/nodenv + 区切り : + PATHの値**/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin**になります。

よって環境変数PATHの値には、もとのPATHに**/Users/mac/.nodenv/bin/nodenv**が追加されたものが代入されることになります。

# PATHの値
PATH=/Users/mac/.nodenv/bin/nodenv:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

# 区切り:で改行
/Users/mac/.nodenv/bin/nodenv 
# ↑追加されている
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin

まとめ

:triangular_flag_on_post: nodenvで通したPATHを読む

export PATH="$HOME/.nodenv/bin:$PATH"

このコードは、PATH変数の値の前$HOME/.nodenv/bin:を追加し、その値をPATH変数に代入する、という意味である。

寄り道① 代入する値を書く時の注意

:warning: 代入する値を''(シングルクォーテーション)で囲むと変数の展開がされない

#ダブルクォーテーション
# export PATH="$HOME/.nodenv/bin:$PATH"
$echo $PATH
PATH=/Users/mac/.nodenv/bin/nodenv:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

#なし
# export PATH=$HOME/.nodenv/bin:$PATH
$echo $PATH
PATH=/Users/mac/.nodenv/bin/nodenv:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

#シングルクォーテーション
# export PATH=’$HOME/.nodenv/bin:$PATH’
$echo $PATH
$HOME/.nodenv/bin:$PATH
# ↑ 環境変数の展開がされていない

寄り道② $PATH:$HOME/.nodenv/bin

export PATH="$PATH:$HOME/.nodenv/bin"

という書き方も見たことがありますが、これはPATHの値の後ろ:$HOME/.nodenv/binを追加し、その値をPATHに代入する、という意味になります。PATHを通すコードの読み方が理解できたので違いが分かりますね。


PATHを通す、ということについて自分なりに調べてみました。「とりあえずやっていたこと」が何をしていたのか理解できると、変更を加える時やエラーが起きた時に対応できるようになるなーと思いました。

#参考

16
22
2

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
16
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?