Windowsでパスを通す

windowsでの環境変数まわりの個人的メモ

## 実行環境
OS : Windows 10 pro

windows PCにjavaの実行環境をつくる事を考えます

## 「パスを通す」って何？
よくプログラミング初学者が環境構築を行う際「パスを通す」というフレーズを見ると思います

まず「パス」ですが、これは**ファイルやフォルダが置いてある場所**のことです

例えばデスクトップ上に適当なテキストファイル(test.txt)があるとします
このファイルのパスは`/c/Users/<ユーザ名>/Desktop/test.txt`となります(windowsの場合)

では、このテキストファイルをコマンドプロンプトの`type`コマンドで表示させてみましょう

```
C:\Users\mk>type test.txt
指定されたファイルが見つかりません。
```

ファイルが見つからないようです
それもそのはず、現在の階層（カレントディレクトリ）直下に`test.txt`というファイルは作成していません
こういう時は`test.txt`の絶対パス（フルパス）を指定すれば現在いるディレクトリがどこであろうと指定できます

```
C:\Users\mk>type C:\Users\mk\Desktop\test.txt
aaa
bbb
c
```

## Java実行環境構築
windowsでJavaのソースコードをコンパイルするためには
先ほどのテキストファイルの例のように、JDKのbinフォルダ（`"C:\Program Files\Java\jdk-14.0.1\bin\java"`）に行かないとコマンドとして使用できません

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

現在のカレントディレクトリに`java`というファイルは存在しないので、当然動きません

```
# 位置をフルパスで指定すれば実行可能
$ "C:\Program Files\Java\jdk-14.0.1\bin\java" -version
java version "14.0.1" 2020-04-14
Java(TM) SE Runtime Environment (build 14.0.1+7)
Java HotSpot(TM) 64-Bit Server VM (build 14.0.1+7, mixed mode, sharing)
```

このように、Javaのコンパイルを行うファイルを絶対パスで指定すれば
バージョンの確認やコンパイルは行えます

でも毎回毎回長ったらしいフルパスを打つのはめんどくさいので
binフォルダへのショートカットみたいなものが欲しいです

**パスを通す**ことで、どこからでもこれらのコマンドを使用できるようにします

```
# pathが通っている状態
$ java -version
java version "14.0.1" 2020-04-14
Java(TM) SE Runtime Environment (build 14.0.1+7)
Java HotSpot(TM) 64-Bit Server VM (build 14.0.1+7, mixed mode, sharing)
```

フルパスで位置を指定してのバージョン確認とpathを通した状態でのバージョン確認は
**やってること自体は同じ**で、環境変数によってパスを補完しているかどうかの違いだという認識です

## setコマンド：環境変数の表示、編集を行う
pathにしか言及していませんが、別に環境変数はpathだけではないです

### すべての環境変数を表示する

```
set
```

```
# 数が多いので途中出力を省略しています
$ set
ALLUSERSPROFILE=C:\ProgramData
APPDATA=C:\Users\mk\AppData\Roaming
・
・
・
USERNAME=mk
USERPROFILE=C:\Users\mk
windir=C:\Windows
```

### 一部の環境変数を表示する

```
set [検索文字列]
```

```
# "user"を含む変数をすべて表示（一部出力を伏せてあります）
$ set user
USERDNSDOMAIN=***
USERDOMAIN=***
USERDOMAIN_ROAMINGPROFILE=***
USERNAME=mk
USERPROFILE=C:\Users\mk
```

### Pathの表示

```
set path
```

```
$ set path
Path=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\Git\cmd;C:\Program Files\Git\mingw64\bin;C:\Program Files\Git\usr\bin;C:\Users\mk\AppData\Local\Microsoft\WindowsApps;C:\Users\mk\AppData\Local\Programs\Microsoft VS Code\bin;C:\Program Files\Java\jdk-14.0.1\bin;C:\Users\mk\Desktop\mk\11_Tools\nkf\vc2005\win32(98,Me,NT,2000,XP,Vista,7)Windows-31J;C:\Users\mk\Miniconda3\Library;
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC

# 読みづらいので出力を';'→'\n'と置換（↑と内容は同じ）
$ set path | tr ; \n
Path=C:\Windows\system32
C:\Windows
C:\Windows\System32\Wbem
C:\Windows\System32\WindowsPowerShell\v1.0\
C:\Windows\System32\OpenSSH\
C:\Program Files\Git\cmd
C:\Program Files\Git\mingw64\bin
C:\Program Files\Git\usr\bin
C:\Users\mk\AppData\Local\Microsoft\WindowsApps
C:\Users\mk\AppData\Local\Programs\Microsoft VS Code\bin
C:\Program Files\Java\jdk-14.0.1\bin
C:\Users\mk\Desktop\mk\11_Tools\nkf\vc2005\win32(98,Me,NT,2000,XP,Vista,7)Windows-31J
C:\Users\mk\Miniconda3\Library

PATHEXT=.COM
.EXE
.BAT
.CMD
.VBS
.VBE
.JS
.JSE
.WSF
.WSH
.MSC
```

#### Pathの役割
pathがいっぱいありますが
```
C:\Program Files\Java\jdk-14.0.1\bin
```
ここに着目します
pathとしてこの文字列が設定されているので、コマンドで単に`java`と打っただけでも
`C:\Program Files\Java\jdk-14.0.1\bin\java`と打ったのと同義になっています

また、すべてのpathに対してこの補完を行っているので
実際のところ
`C:\Windows\system32\java`
`C:\Windows\java`
`C:\Windows\System32\Wbem\java`
と、上から順番に見て成立するフルパスを探しているようです

#### PATHEXTとは
補完を試みる拡張子のリストで、このリストに存在する拡張子のファイルならば拡張子の指定なしで実行できます
本来は`java.exe`ですが`java`のみの入力で実行できたのは
このリストに`.EXE`が含まれていたためです

#### 余談
これは自分だけかもしれませんが、環境変数の中でもぶっちぎりで長い分量の文字列が格納されているので
```
Path=C:\Windows\system32;・・・\Library;
```
が**一行の値**だと認識できていませんでした
（あくまでセミコロンを区切り文字としているだけ）
windows 8などで環境変数を設定する場合は一行でドン！と表示されているかと思うので
元々のpathの値を削除しないように気をつけてください

## Pathの設定について
「windows 10 path」とかで調べるとたくさん情報がでてくるのでそちらをご覧ください
CUIでの設定とGUIでの設定両方がありますが、
windows 10以降であれば個人的にはGUIでの設定がわかりやすくて安全だと思います
（windows 8とかだと表示がちょっと見づらい）

### CUI（setxコマンドなど）で設定したい
setコマンドで設定すると、コマンドプロンプトを終了するとその時点で設定は消えてしまいます
setxコマンドで永続的に設定を反映させることができるようですが、
pathの文字数が長い場合[^1]や、システム環境変数をユーザー環境変数でオーバーライドする場合[^2]など
問題が発生するケースがあるようなので、注意が必要です。（あまりお勧めされていない）


[^1]: [保存されたデータは1024文字に切り捨てられました。(復旧済）](https://qiita.com/cp3/items/856339499aaae20e4da2)


[^2]: [Windows環境変数の設定に「SETX」コマンドを使ってはいけない理由](https://qiita.com/jeyei/items/05ce2739501832463b3b)


## 参考
[「PATH を通す」の意味をできるだけわかりやすく説明する試み](https://qiita.com/sta/items/63e1048025d1830d12fd)
調べた中で一番わかりやすかった記事です

[Javaの環境変数の設定方法](https://eng-entrance.com/java-install-env)
Javaの環境構築を前提として、GUIでの環境変数の設定方法がスクショつきで解説してあります

[Windows環境変数の超基本を理解する為のアプローチ](https://qiita.com/jeyei/items/2c385e4e0488a5fa2591)
pathだけでなく環境変数全体の話をかなり詳しく丁寧に解説してあります
GUIでのpath設定とsetコマンドでのpath設定では指している場所が違うことなどの解説もあります