Javaをインストールしたはずなのに、java と打つとこう言われます。

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

PowerShell(Windows PowerShell 5.1)なら「用語 ‘java’ は、コマンドレット、関数、スクリプト ファイル、または操作可能なプログラムの名前として認識されません」です。どちらも、インストールに失敗したように見えます。

実際には、java.exe はディスクの上にちゃんとあります。インストール先のフォルダーを開き、そこで java と打てば動きます。プログラムが無いのではなく、Windowsが探しに行った場所に無かっただけです。

エラーの文面は「認識されていません」ですが、中身は「探した範囲では見つからなかった」という報告です。この記事では、Windowsがコマンドをどこから、どの順番で探しているのかを整理し、「パスを通す」とは何をすることなのか、そして通したのに動かないときにどこを確かめるのかをまとめます。

名前だけで動くのは、Windowsが決まった場所を探しているから

コマンドプロンプトで cmd や ping と打つと動きます。このとき裏で実行されているのは、C:\Windows\System32\cmd.exe や C:\Windows\System32\ping.exe というファイルです。私たちは場所も拡張子も書いていません。それでも動くのは、Windowsが2つのことを補っているからです。

  • 拡張子: ping と打てば ping.exe・ping.bat などを候補にする。補う拡張子の一覧は環境変数 PATHEXT に入っている
  • 場所: 決められたフォルダーを順番に探し、最初に見つかったものを実行する

この「決められたフォルダーの一覧」が、環境変数 Path です。「パスを通す」とは、この一覧にフォルダーを1行足すことにすぎません。

Pathは「探す場所」の一覧で、上から順に見る

一覧の中身はすぐに見られます。

REM コマンドプロンプト
set Path

# PowerShell(1行ずつに分けて表示)
$env:Path -split ';'

C:\Windows\system32;C:\Windows;... のように、フォルダーがセミコロン区切りで並んでいます。Windowsはこれを先頭から順に見て、最初に見つかったものを実行します。

set と打つと環境変数がずらりと並び、その中に Path= の行があります。そこからJavaのフォルダーを見つけ、エクスプローラーで開くと本当に java.exe が入っている——という確かめ方は、動画の2分45秒あたりから(無料)そのまま見られます。環境変数という言葉に身構える人ほど、一度画面で見ておくと「ただの文字列の一覧だ」と分かります。

ここから大事な性質が1つ出てきます。同じ名前のプログラムが複数あったら、一覧の上にあるほうが勝つ。 Javaを2つのバージョンで入れていると、新しいほうを入れたのに古いほうが動く、ということが普通に起きます。実際にどれが選ばれているかは、次のコマンドで確かめます。

REM コマンドプロンプト:見つかった順に全部表示する
where java

# PowerShell:実際に実行されるものを表示する
Get-Command java
where.exe java

PowerShellでは where だけだと別のコマンド(Where-Object の別名)が動いてしまうので、where.exe と拡張子まで書きます。

場所を書けば、Pathは関係なくなる

Pathは「名前だけで打ったとき」に使われる仕組みです。場所を書けば、Pathに載っていなくても実行できます。書き方は3つあります。

書き方 例 意味
フルパス C:\Program Files\...\bin\java.exe ドライブの根元から全部書く。どこにいても同じものを指す
相対パス .\bin\java.exe、..\java.exe 今いる場所から見た位置。. は今の場所、.. は1つ上
名前だけ java 書いていない部分をWindowsが探す。ここで初めてPathが使われる

Pathから一度Javaのフォルダーを消すと、名前だけでは冒頭のエラーになります(6分16秒あたり)。それでも、そのフォルダーに移動して打てば動き(6分50秒あたり)、1つ上のフォルダーからは相対パスで(8分あたり)、どこに移動していてもフルパスで動きます(9分50秒あたり)。同じ java.exe を、場所の書き方だけ変えて順に呼び出していく流れは、画面で見ると一度で腑に落ちます。

フルパスは、エクスプローラーでファイルを Shiftキーを押しながら右クリック →「パスのコピー」で取れます。手で打つより確実です。

スクリプトやタスクスケジューラのように「誰の、どの設定で動くか分からない」場所では、Pathに頼らずフルパスで書くほうが安全です。対話で毎日打つコマンドだけをPathに任せる、という使い分けになります。

コマンドプロンプトとPowerShellで違う、ただ1つの点

ここは動画の外の補足ですが、PowerShellを使う人ほど引っかかる点です。

コマンドプロンプトは、名前だけで打たれたときまず今いるフォルダーを探し、見つからなければPathを探します。だから、java.exe のあるフォルダーに移動すれば java だけで動きました。

PowerShellは、今いるフォルダーを探しません。 これはセキュリティのための仕様で、Microsoftのドキュメント(about_Command_Precedence)にも明記されています。今いるフォルダーのプログラムやスクリプトを動かすには、.\ を付けて「ここにあるこれ」と場所を書きます。

java        # 今いるフォルダーに java.exe があっても、Pathに無ければエラー
.\java      # 動く
.\setup.ps1 # スクリプトも同じ

コマンドプロンプトの感覚のまま「このフォルダーにあるのに認識されない」と悩んだら、.\ を疑ってください。なお、.\ を付けても .ps1 が動かない場合は、場所ではなく実行ポリシーの問題です。エラーの文面が違う(「このシステムではスクリプトの実行が無効になっている」)ので区別できます。実行ポリシーを確かめて変える手順は、スクリプト実行の動画の1分50秒あたりから(無料)で見られます。

パスを通す手順と、通したのに効かない罠

Pathに足すのは、Windowsの「環境変数」画面です。スタートメニューで「システム環境変数の編集」と検索するか、「システム」→「システムの詳細設定」→「環境変数」とたどります。

画面には ユーザー環境変数 と システム環境変数 の2段があり、どちらにも Path があります。

  • ユーザー環境変数の Path: 自分のアカウントだけに効く。管理者権限が要らない
  • システム環境変数の Path: そのPCの全ユーザーに効く。管理者権限が要る

実際に使われるPathは、システムのPathの後ろにユーザーのPathをつないだものです。同じ名前のプログラムがあればシステム側が先に見つかる、という点は覚えておくと役に立ちます。

Path を選んで「編集」を押すと、フォルダーが1行ずつ並んだ画面になります。「新規」で、実行ファイルそのものではなく、実行ファイルが入っているフォルダーを貼り付けます(...\bin\java.exe ではなく ...\bin)。画面をたどって1行足すまでの一連の操作は、12分あたりから通しで見られます。

そして、いちばん多い罠がこれです。設定を変えても、すでに開いているウィンドウには反映されません。 コマンドプロンプトもPowerShellも、起動した瞬間の環境変数を持ったまま動き続けます。足したのに「認識されない」と言われたら、まずウィンドウを閉じて開き直してください(5分48秒あたりで動画でも注意しています)。ターミナルアプリのタブを足しても古いままのときは、アプリごと閉じ直します。

Pathから消してはいけない場所がある

Pathの一覧には、最初から入っている行があります。代表が %SystemRoot%\system32 です。

%SystemRoot% は別の環境変数を参照する書き方で、中身は通常 C:\Windows です。つまりこの行は C:\Windows\system32 を指しています。ping・ipconfig・cmd などWindows標準のコマンドの多くはここにあり、どこからでも名前だけで打てるのはこの1行のおかげです。

試しにこの行を消すと、ping すら「認識されていません」になります(14分37秒あたり)。普段意識しない標準コマンドまで、全部Pathに支えられていたことが分かる場面です。Pathを編集するときは、足すことはあっても、元からある行は消さない。整理したくなっても、何が入っているのか分からない行には触らないのが原則です。

「認識されません」を見たときに確かめる順番

順 確かめること 確かめ方
1 そもそも入っているか インストール先のフォルダーに実行ファイルがあるか、エクスプローラーで見る
2 場所を書けば動くか フルパスで実行する。動くならプログラムは無事で、問題は探す場所だけ
3 Pathに載っているか $env:Path -split ';' または set Path に、実行ファイルのあるフォルダーがあるか
4 開き直したか 設定を変えたあと、ウィンドウ(ターミナルアプリ)を閉じて開き直したか
5 別のものが先に見つかっていないか where.exe java で複数出たら、上にあるものが実行されている
6 PowerShellで今のフォルダーのものを動かそうとしていないか .\ を付けて実行する

2で動くなら、残りはすべて「探す場所」の問題です。再インストールを繰り返す前に、ここまでを確かめてください。

まとめ

  • 「認識されません」は、プログラムが無いという意味ではない。探した場所に無かったという意味
  • Pathは「名前だけで打ったときに探すフォルダーの一覧」。先頭から順に見て、最初に見つかったものが動く
  • 場所を書けば(フルパス・相対パス)、Pathは関係なくなる。スクリプトではフルパスが安全
  • PowerShellは今いるフォルダーを探さない。そこにあるものは .\ を付けて動かす
  • Pathに足したら、ウィンドウを開き直す。元からある行(%SystemRoot%\system32 など)は消さない