【CMD】環境変数PATHについて -“PATHを通す”とは-

コマンドプロンプト

“PATHを通す” とは何をすれば良いのか、'xxx' は、内部コマンドまたは外部コマンド、操作可能なプログラムまたはバッチ ファイルとして認識されていません。というエラーが出た時はどのように対応すれば良いのか、環境変数 PATH について整理しながら解説していきます。

PATHを通す

エラー「’xxx’ は、… として認識されていません。」

コマンドプロンプトで何かコマンドを実行しようとすると、次のようなエラーが出力されることがあります。

$ git -v
'git' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
$ npm -v
'npm' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
$ java --version
'java' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

このエラーの原因は “PATHが通っていない” ことです。

原因
実行したいコマンドのプログラムが、環境変数PATHに設定されていないため。
= “PATHが通っていない” ため。

従ってこの問題を解消するには、”PATHを通す” 必要があります。そしてそのためにはまず、環境変数 PATH について理解する必要があります。

最終的にやることは設定を一つ追加するだけなので、少し遠回りに見えるかもしれませんが、順を追って環境変数 PATH について見ていくことで、今後同じ問題に遭遇しても容易に対応できるようになります。

コマンドの実行(=実行ファイルの指定)

まず初めに、”コマンドを実行する” とは「実行ファイルを指定して、そこに記載されたプログラムを実行する」ことであるということを理解する必要があります。

コマンドと聞くと、何かPCに組み込まれた特別な物、と思ってしまうかもしれませんが、実際には ○○.exe△△.bat のような、PCのどこかに保存されている単なるファイルに過ぎません。そしてコマンドを実行するとは、そのファイルに記載されたプログラムを実行するということです。

詳細に理解する必要はありませんが、なんとなくでもこのイメージを持っておくと、これ以降の手順が分かりやすくなります。何もないところから突然、特定の文字列がコマンドとして利用できるようになっているわけではなく、実体となるファイルが存在する、ということです。

これについて、簡単な bat ファイルを使って確認してみます。

最初に検証用の空の作業ディレクトリ(ここではC:\Users\xxx\workspace\sample)を用意します。

次にこのディレクトリでコマンドプロンプトを開きます。

こちらの手順で簡単に開くことができます。

そしてここに、以下のような「Hello World」を出力するだけの簡単なサンプルプログラムを記述した greet.bat を配置します。

@echo off

echo Hello World

ここで、greet.bat と打つと、この bat ファイルに記述されたプログラムを実行することができます。

$ greet.bat
Hello World

ファイル名が .bat の場合、拡張子を省略することもできます。これは環境変数 PATHEXT.BAT が設定されているためです。

$ greet
Hello World

上の例で示した通り、$ greet のように拡張子を省略しても $ greet.bat を実行することができます。これは環境変数 PATHEXT.BAT が設定されているためです。
同じように java.exegit.exenpm.cmd も、PATHEXT.EXECMD がそれぞれ設定されているため、単に javagitnpm と打つだけで実行することができます。

$ set PATHEXT
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC

そしてこれが “コマンドを実行する” ということです。環境変数 PATHEXT に設定された種類のファイルは、拡張子を含めずファイル名だけを指定して呼び出せることもあって「コマンドの実行=実行ファイルの指定」というイメージが湧きにくいかもしれません。しかしこのことから、コマンドを実行するとはすなわち、PC内に配置された実行ファイルを指定して呼び出し、そこに書かれたプログラムを実行することだと分かります。

コマンドを実行する
= 拡張子を省略して実行ファイルを指定する。
= 実行ファイルを指定して呼び出し、記述されたプログラムを実行する。

別のディレクトリで実行(=認識されていません。)

ここまでで greet コマンドが実行できるようになりました。しかしこのコマンドはこのディレクトリでしか実行できません。なぜなら greet コマンドによって実行されている greet.bat が、今いる C:\Users\xxx\workspace\sample に配置されているファイルだからです。

試しに別のディレクトリに移動して実行してみます。C:\Users\xxx\workspace に新しく空の empty ディレクトリを作成し、そこへ移動してから greet コマンドを実行してどうなるかを確認します。

$ cd ..\empty

$ greet
'greet' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

想定通り実行できず、エラーが出力されました。そしてここで、問題となっているエラー出力を得ることができました。従って、この 'xxx' は、内部コマンドまたは外部コマンド、操作可能なプログラムまたはバッチ ファイルとして認識されていません。というエラーは、コマンドを実行しようとした(=指定されたファイル名から実行ファイルを呼び出そうとした)が、そこにファイルが無かったために発生した、ということが分かります。

これが分かれば、このエラーの解決方法が二つ浮かびます。

  • 案1:empty ディレクトリに greet.bat をコピーする。
  • 案2:ファイル名だけでなくパスを含めることで sample 下にある greet.bat を指定する。

実際に試してみると、どちらもうまくいくことが分かります。

# 案1
# workspace\sample\greet.bat を今いる workspace\empty へコピー
$ copy ..\sample\greet.bat .\greet.bat
        1 個のファイルをコピーしました。

# workspace\empty ディレクトリでも実行できる
$ greet
Hello World

# 案2
# パスを含めて greet.bat を指定すればコピーしなくても実行できる
$ ..\sample\greet
Hello World

さらに、絶対パスを指定するようにすれば、コピーも不要で、どこのディレクトリへ移動しても同じようにコマンドを実行できます。

# 絶対パスを指定すればカレントディレクトリを問わずコマンド実行可能
$ C:\Users\xxx\workspace\sample\greet
Hello World

これで問題は解消しました。最初に例示した gitnpmjava のエラーも、全てこの方法で解決できるはずです。実際、以下のように npm コマンドを動作させることにも成功しました。

# npm コマンドでエラー
$ npm -v
'npm' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

# 絶対パスを指定すれば実行できる
# ※ 絶対パスを "" で囲んでいるのは「Program Files」に半角スペースが含まれるため
$ "C:\Program Files\nodejs\npm" -v
10.8.2
  • カレントディレクトリにファイルがある場合
    • 実行ファイルを呼び出すことができる
      • 例)$ greet.bat
    • PATHEXTに拡張子が含まれていれば省略できる
      • 例)$ greet(=よく見るコマンド実行の形)
  • カレントディレクトリにファイルがない場合
    • 絶対パスを指定すれば呼び出すことができる
      • 例)$ C:\Users\xxx\workspace\sample\greet.bat
    • PATHEXTに拡張子が含まれていれば省略できる
      • 例)$ C:\Users\xxx\workspace\sample\greet

一応これで問題を解決することはできましたが、毎回コマンド実行の度に絶対パスを指定するのは大変です。それに、いつも例えば npm コマンドを実行する時など、パスを含めるようなことはしていないと思います。そこで、絶対パスを指定しなくてもよくなる仕組みを利用します。ここで出てくるのが、環境変数 PATH です。(環境変数とは

環境変数PATHの利用(=PATHを通す)

環境変数 PATH に設定されている値を確認してみると、以下のような長い文字列が出力されます。

$ echo %PATH%
C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\Docker\Docker\resources\bin;C:\Program Files\nodejs\;・・・

一見よく分かりませんが、複数のパスが連なっていることが確認できます。; は区切りを意味するため、複数のディレクトリの絶対パスの列挙が設定されているということです。

PATH = C:\Windows\system32, C:\Windows, C:\Windows\System32\Wbem, …

そしてこの複数のパスは、先頭から順に優先順位が高くなっています。

  • 環境変数 PATH
    • 優先順位1:C:\Windows\system32
    • 優先順位2:C:\Windows
    • 優先順位3:C:\Windows\System32\Wbem
    • ・・・

環境変数 PATH について上記を踏まえ、再度 greet コマンドを例に見ていきます。

例えば先ほども確認した以下のエラー、greet.bat を配置した workspace\sample の絶対パスを指定すれば良いということは検証済みですが、このエラーは単純に、workspace\emptygreet.bat が存在しないから、というだけで出力されているわけではありません。

# カレントディレクトリは「workspace\empty」
$ cd
C:\Users\xxx\workspace\empty

# greet.bat が存在しないためエラー
$ greet
'greet' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

カレントディレクトリ C:\Users\xxx\workspace\emptygreet.bat がないと判明した後、すぐにエラーが出るのではなく、次に環境変数 PATH に設定されたディレクトリを見に行きます。そして、優先順位に従って(=PATHに設定されたパスを先頭から順に)確認し、greet.bat を探します。こうして PATH に設定されたディレクトリ全てに greet.bat が存在しなかった場合に初めてこのエラーが出力されます。

PATH = C:\Windows\system32, C:\Windows, C:\Windows\System32\Wbem, … の場合

① カレントディレクトリに greet.bat がない

② エラー「 ‘greet’ は、・・・として認識されていません。」

① カレントディレクトリに greet.bat がない

② C:\Windows\system32 に greet.bat がない

③ C:\Windows に greet.bat がない

④ C:\Windows\System32\Wbem に greet.bat がない

・・・

ⓝ エラー「 ‘greet’ は、・・・として認識されていません。」

厳密には、環境変数 PATH のディレクトリから実行ファイルを探し出す際、環境変数 PATHEXT に設定した拡張子に一致するファイルがないかということも順番に確認しています。例えば、PATHEXT.EXE;.BAT;.CMD; が設定されていた場合、次のような挙動になります。(PATHEXTPATH と同じように、設定された順に先頭から優先順位が高くなります。)

$ set PATHEXT
PATHEXT=.EXE;.BAT;.CMD;

① カレントディレクトリに greet.exe がない

② カレントディレクトリに greet.bat がない

③ カレントディレクトリに greet.cmd がない

④ C:\Windows\system32 に greet.exe がない

⑤ C:\Windows\system32 に greet.bat がない

⑥ C:\Windows\system32 に greet.cmd がない

⑦ C:\Windows に greet.exe がない

⑧ C:\Windows に greet.bat がない

⑨ C:\Windows に greet.cmd がない

⑩ C:\Windows\System32\Wbem に greet.exe がない

⑪ C:\Windows\System32\Wbem に greet.bat がない

⑫ C:\Windows\System32\Wbem に greet.cmd がない

・・・

ⓝ エラー:「 ‘greet’ は、・・・として認識されていません。」

環境変数PATH
;区切りで複数のディレクトリパスが設定されている。コマンドが実行(=実行ファイルが指定)されると、先頭に設定されたディレクトリパスから順に対象ファイルがないか確認し、一致すれば実行する。

ここまで分かれば、あとは次の二つの解決策が浮かぶと思います。

  • PATH に設定されているいずれかのディレクトリに greet.bat を置く。
  • greet.bat がある C:\Users\xxx\workspace\samplePATH に追加する。

通常は後者で対応することになりますので、次のコマンドを実行します。

$ set PATH=%PATH%;C:\Users\xxx\workspace\sample
環境変数の追加方法はこちらにも記載しています。

これで “PATHを通す” ことができました。greet.bat を配置したディレクトリでなくても、絶対パスを指定せず、コマンド実行できることが確認できます。

# カレントディレクトリは「workspace\empty」
$ cd
C:\Users\xxx\workspace\empty

# 環境変数PATHにC:\Users\xxx\workspace\sampleを追加した(PATHを通した)ため
# greet.bat がないところでもコマンドを実行(batファイルを指定)できる
$ greet
Hello World

パスを追加する際、区切りを意味する ; を入れ忘れると、正しくディレクトリが認識されなくなってしまいます。そのため、実施後は echo 等で想定通りに追加されているか確認することが肝要です。

# 既存の PATH は「;」で終わっていない
$ echo %PATH%
C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem

#「%PATH%」と「C:\Users\xxx\workspace\sample」の間に「;」を入れ忘れる
$ set PATH=%PATH%C:\Users\xxx\workspace\sample

#「C:\Windows\System32\WbemC:\Users\xxx\workspace\sample」という
# ディレクトリが追加されたことになってしまっている
$ echo %PATH%
C:\Windows\system32;C:\Windows;C:\Windows\System32\WbemC:\Users\xxx\workspace\sample
# 既存の PATH は「;」で終わっていない
$ echo %PATH%
C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem

#「%PATH%」と「C:\Users\xxx\workspace\sample」の間に「;」を忘れないよう注意
$ set PATH=%PATH%;C:\Users\xxx\workspace\sample

# 実施後は想定通りに追加されているか出力して確認
$ echo %PATH%
C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Users\xxx\workspace\sample

パスを追加する際、末尾に追加する方法だと場合によっては意図した通りに反映されないことがあります。

例えば既に既存のバージョンのコマンドにPATHが通っており、一時的に異なるバージョンにPATHを通して変更したかったとします。この時、末尾に新しいディレクトリを追加しても、それよりも前の位置に既存のディレクトリが設定されている状態になります。PATHに設定された値は、先頭に近いほど優先順位が高くなるため、バージョン違いの同じコマンドのような場合は、末尾に追加しても反映されません。

このような場合は、次に示すように、先頭に追加したり、値を置換したりして対応する必要があります。

末尾に追加した場合(反映されない)

# 一時的に「C:\java\jdk-17.0.13\bin」にPATHを通したい
$ set PATH
Path=C:\Windows\system32;C:\java\jdk-23.0.1\bin;C:\Program Files\nodejs\

# 末尾に値を追加する
$ set PATH=%PATH%;C:\java\jdk-17.0.13\bin

#「C:\java\jdk-23.0.1\bin」より後に「C:\java\jdk-17.0.13\bin」がある
$ set PATH
Path=C:\Windows\system32;C:\java\jdk-23.0.1\bin;C:\Program Files\nodejs\;C:\java\jdk-17.0.13\bin

# 先頭に近いほうが優先され「C:\java\jdk-17.0.13\bin」が反映されない
$ java --version
java 23.0.1 2024-10-15
Java(TM) SE Runtime Environment (build 23.0.1+11-39)
Java HotSpot(TM) 64-Bit Server VM (build 23.0.1+11-39, mixed mode, sharing)

方法1: 先頭に挿入する

# 一時的に「C:\java\jdk-17.0.13\bin」にPATHを通したい
$ set PATH
Path=C:\Windows\system32;C:\java\jdk-23.0.1\bin;C:\Program Files\nodejs\

# 先頭に値を挿入する
$ set PATH=C:\java\jdk-17.0.13\bin;%PATH%

#「C:\java\jdk-23.0.1\bin」より前に「C:\java\jdk-17.0.13\bin」がある
$ set PATH
Path=C:\java\jdk-17.0.13\bin;C:\Windows\system32;C:\java\jdk-23.0.1\bin;C:\Program Files\nodejs\

# 先頭に近いほうが優先され「C:\java\jdk-17.0.13\bin」が反映される
$ java --version
java 17.0.13 2024-10-15 LTS
Java(TM) SE Runtime Environment (build 17.0.13+10-LTS-268)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.13+10-LTS-268, mixed mode, sharing)

方法2: 対象の文字列を置換する

# 一時的に「C:\java\jdk-17.0.13\bin」にPATHを通したい
$ set PATH
Path=C:\Windows\system32;C:\java\jdk-23.0.1\bin;C:\Program Files\nodejs\

#「C:\java\jdk-23.0.1\bin」を「C:\java\jdk-17.0.13\bin」に置換する
$ set PATH=%PATH:C:\java\jdk-23.0.1\bin=C:\java\jdk-17.0.13\bin%

#「C:\java\jdk-23.0.1\bin」が「C:\java\jdk-17.0.13\bin」に置き換わっている
$ set PATH
Path=C:\Windows\system32;C:\java\jdk-17.0.13\bin;C:\Program Files\nodejs\

# 置き換えられた「C:\java\jdk-17.0.13\bin」が反映される
$ java --version
java 17.0.13 2024-10-15 LTS
Java(TM) SE Runtime Environment (build 17.0.13+10-LTS-268)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.13+10-LTS-268, mixed mode, sharing)

方法3: 対象の文字列を削除してから末尾に追加する

# 一時的に「C:\java\jdk-17.0.13\bin」にPATHを通したい
$ set PATH
Path=C:\Windows\system32;C:\java\jdk-23.0.1\bin;C:\Program Files\nodejs\

#「C:\java\jdk-23.0.1\bin;」を削除する
#「C:\java\jdk-23.0.1\bin;」を空文字に置換(=削除)
$ set PATH=%PATH:C:\java\jdk-23.0.1\bin;=%

# 末尾に値を追加する
$ set PATH=%PATH%;C:\java\jdk-17.0.13\bin

#「C:\java\jdk-23.0.1\bin」が消えて末尾に「C:\java\jdk-17.0.13\bin」がある
$ set PATH
Path=C:\Windows\system32;C:\Program Files\nodejs\;C:\java\jdk-17.0.13\bin

# 末尾に追加された「C:\java\jdk-17.0.13\bin」が反映される
$ java --version
java 17.0.13 2024-10-15 LTS
Java(TM) SE Runtime Environment (build 17.0.13+10-LTS-268)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.13+10-LTS-268, mixed mode, sharing)
環境変数の値の置換や一部削除の方法はこちらに記載しています。

PATHを通す
= 環境変数 PATH に 対象のファイルがあるディレクトリを追加する。
= 絶対パスを指定しなくてもファイル名だけで実行ファイルを指定できるようにする。
= 指定したコマンドを実行できるようにする。

環境変数PATHの要点

まとめると以下の通りです。

  • 環境変数 PATH とは
    • コマンド実行の際に使用されるパスのリスト。コマンドが実行(実行ファイルが指定)された際、カレントディレクトリに存在しなければ、この変数に ; 区切りで複数設定されたディレクトリを先頭から順に見に行く。該当するファイルがあればそれを実行する。
  • エラー「’xxx’ は、… として認識されていません。」
    • コマンドが実行(実行ファイルが指定)された際、指定された実行ファイルがカレントディレクトリに存在せず、環境変数 PATH に設定された全てのディレクトリいずれにも存在しない場合に発生する。PATHを通すことで解消する。
  • PATHを通す
    • 環境変数 PATH に、対象のコマンド(=実行ファイル)が配置されたディレクトリを追加すること。これによって、絶対パスを指定したり、実行ファイルがあるディレクトリまで移動したりしなくても、対象のコマンド(=実行ファイル)を実行できるようになる。

その他

環境変数PATHの永続的な設定

ここまでに行った set コマンドによる PATH への追加は、あくまで一時的な設定となります。そのためコマンドプロンプトを閉じると変更は消えてしまいます。また閉じなかったとしても、他のコマンドプロンプトからは参照することができません。

そこで、永続的に PATH へ追加し、以降すべてのコマンドプロンプトで使用できるようにするには、環境変数の設定画面から追加を行う必要があります。詳細は以下を確認してください。

環境変数 PATH の永続設定の詳細はこちらです。

コマンドPATHの利用

PATH は環境変数の変数名ですが、これとは別に同名のコマンドとしても用意されています。このコマンド PATH を使用して、環境変数 PATH を表示したり設定したりすることが可能です。

# 環境変数ではなくコマンドの PATH を使ってヘルプを出力することが可能
$ PATH /?
実行可能ファイルの検索パスを表示または設定します。

PATH [[ドライブ:]パス[;...][;%PATH%]]
PATH ;

パラメーターとして ; (セミコロン) だけを指定すると、すべての検索パスはクリアされて
現在のディレクトリだけが検索されます。
パラメーターの指定がなければ、現在のパスが表示されます。
新しいパス設定に %PATH% を指定すると、前のパスが新しい設定に追加されます。

例えば引数を指定せずに実行すれば、現在の PATH の値を出力することができます。set でも同じことができますが、前方一致により PATHEXT も同時に出力されてしまうため、PATH コマンドのほうが出力が分かりやすくなります。

# set を使用すると PATH で始まる PATHEXT も出力されてしまう
$ set PATH
Path=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;・・・
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC

# echo に PATH の値を指定すれば PATH のみ出力することができる
$ echo %PATH%
C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;・・・

# コマンドの PATH を使用すれば echo で参照を出力する必要もない
$ PATH
PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;・・・
タイトルとURLをコピーしました