汝、コマンドプロンプトを愛せよ

# 汝、コマンドプロンプトを愛せよ
Windowsの自動化の基本となるものにコマンドプロンプトと、そこから実行できるバッチファイルがあります。

Windowsのバッチファイルは古いマシンから新しいマシンまで使用できます。


今回は、それをまとめてみようと思いますが、百番煎じくらいになるので、なるべくMicrosoftが提供するドキュメントをベースになるように話を進めたいと思います。
文中のリンクは基本的に公式サイトへのリンクになっているので必要に応じて参照してください。

>※注意
なにがなんでもバッチファイルで書けという趣旨の記事ではありません。最近はPowerShellも使えますし、レガシーの環境ではWSHという選択肢もあります。



## 汝、ヘルプを愛せよ
コマンドプロンプトでなんらかの操作を行う場合、手っ取り早くコピペですますのもよくあることですが、基本的にはヘルプを確認するようにしましょう。コピペ元のコマンドやオプションをよくわからないままつかって、動かなかったり、ひどい目にあうことは、よくあることです。

結局、自分自身がこれから行う作業にとって、実行するコマンドやオプションが適切かどうか判断するには公式が提供するヘルプをみるしかないのです。

では、そのとっかかりとして、コマンドプロンプトで以下のコマンドを実行してみましょう。

```
help
```

コマンドプロンプトで使用できる主だったコマンドの一覧が取得できると思います。
ここで特定のコマンドの詳細を確認したい場合は以下のようにhelpの後にコマンド名を実行します。

```
help dir
```

dirコマンドの詳細の使い方が表示されました。
helpコマンドはコマンドプロンプトやバッチファイルで使用するコマンドの詳細を表示してくれます。しかしながら、すべてのコマンドのヘルプをサポートしているわけではありません。

もし、「help コマンド名」でヘルプが表示されなかったら「コマンド名 /?」を実行してみてください。

### ヘルプで不十分だった場合は？
実際のところ、helpコマンドで表示されるヘルプに全ての情報がのっているわけではありません。
次に読むべきものはMicrosoftが提供するドキュメントです。
たとえば、以下からコマンドのリファレンスのリンクが存在します。

https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/windows-commands

Microsoftが提供するインターネット上のドキュメントは昨今、機械翻訳になっていたり、そもそも日本語対応していなかったり、数年たったらなんか消えている場合があったりしますが、もっとも尊重すべきドキュメントの一つです。

この文章を含めた個人サイトを読むのは、あくまでおまけとして、公式が何を言っているかをつかむようにしましょう。

## コマンドプロンプトの起動方法
コマンドプロンプトは「Winキー＋R」を押した後に「cmd.exe」と入力すると起動します。
ここではコマンドプロンプトの起動についての話をいくつかしようと思います。

### 特定のディレクトリをカレントディレクトリとしてコマンドプロンプトを起動したい
たとえば、特定のディレクトリをカレントディレクトリとしてコマンドプロンプトを起動したい場合がよくあると思います。
その場合はショートカットを使用すると楽です。

1. ショートカットを新規に作成します。任意のディレクトリで右クリックして新規作成を選択するとショートカットが作成できます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/f2502d5e-0b0e-0165-04b9-5b81523d830d.png)

2. 項目の場所には「%windir%\system32\cmd.exe」を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/c74d2c08-9edb-28f9-bc23-0d499150f38b.png)

3. ショートカット名はわかりやすい任意の名前をつけてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/5838713f-a724-d4f3-d40e-256ef066cb01.png)

4. 作成されたショートカットのプロパティを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/f81bead0-a932-8458-1af2-4a311665def6.png)

5. 作業ディレクトリに「%CD%」と入力して適用を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/c6c89a93-66c8-020c-7a95-a6c18792ad60.png)

6.以後ショートカットを起動すると、ショートカットを作成したディレクトリをカレントディレクトリとしてコマンドプロンプトが起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/e6609124-9605-4400-3a58-fcc8a57cccc7.png)

もし、このショートカットでの起動時に特定のコマンドを実行したい場合はリンク先を以下のように記載します。

```
%windir%\system32\cmd.exe /k C:\dev\python3\py3env.bat
```

[kオプション](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cmd)の後に実行したいバッチファイルを指定してください。
指定したバッチファイルを実行した後に、コマンドプロンプトが操作可能になります。
これは特定の環境変数を定義してあるコマンドプロンプトを使用するのに便利なテクニックになります。


### 起動したコマンドプロンプトすべてで初期処理を実行したい場合
下記のレジストリに実行したいバッチファイルのパスを記載することで起動時の初期処理を記載できます。

 - HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\AutoRun
 - HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun

HKEY_LOCAL_MACHINEはローカルPCすべてのユーザで実行される処理で、HKEY_CURRENT_USERは現在のユーザのみで実行される処理になります。
実行順番としてはHKEY_LOCAL_MACHINE→HKEY_CURRENT_USERとなります。

[cmd.exe](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cmd)を実行する場合にdオプションをつけることで、AutoRunを無視することが可能です。

```
REM 初期処理が実行してからt.batが動作する
cmd /c t.bat

REM 初期処理が実行されないでt.batが動作する
cmd /d /c t.bat
```

## コマンドプロンプトの操作

### 履歴操作
コマンドラインで実行したコマンドは履歴として保持しており、再実行することが可能です。

#### F7キーによる履歴の表示
F7キーを押下することで履歴を表示可能です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/3c4da53f-23be-3659-7c54-7d82546361cd.png)

またカーソルを上下にうごかして、Enterキーを押すことで、再実行が可能になっています。

#### doskeyコマンドによる履歴の表示
[doskeyコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/doskey)のhistoryオプションを使用することで履歴の一覧が表示されます。

```
doskey /history
```

#### カーソルキーとPageUp、PageDownによる履歴の選択

|キーボード|説明|
|:---------|:---|
|↑|現在表示されている前の履歴のコマンドを実行します|
|↓|現在表示されている後の履歴のコマンドを実行します|
|PageUp|履歴の最古のコマンドを呼び出します|
|PageDn|履歴の最新のコマンドを呼び出します|

カーソルキーの↑または↓を押下することで過去の履歴を選択することが可能です。

#### 前方一致による履歴の選択
過去に実行したコマンドを途中まで入力した時点でF8を押下すると過去の履歴から前方一致するコマンドを実行します。複数ある場合は、もう一度F8を押下することで切り替えられます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/a96aa629-a150-754f-53ce-cfac4a95ee11.png)

F8の押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/6f143a47-fab8-2bea-711b-cafd42677f9a.png)

#### 履歴の番号による選択
F9を入力することで数値で履歴を選択できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/1e55b5c0-cd21-43fc-e178-4d43e1b2d2d8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/f537f95a-e81f-e5c7-749b-13b4b16fcd04.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/006b517c-cbf2-581b-8859-4918cf44adb3.png)

#### 履歴の消去
Alt+F7で履歴をすべて消去します。

### マクロ
[doskeyコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/doskey)を使用することでマクロを登録可能です。
これにより複数の操作を一つのコマンドで実行したり、PowerShellでいうようなAliasのような使い方ができます。
なお、下記のヘルプにあるようにコマンドのヘルプにあるようにdoskeyコマンドで作成したマクロはバッチファイルから実行できません。

https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/doskey

>Running a doskey macro
>
>To run a macro, type the macro name at the command prompt, starting at the first position. If the macro was defined with \$\\* or any of the batch parameters \$1 through \$9, use a space to separate the parameters. **You cannot run a doskey macro from a batch program.**

#### マクロの登録
##### コマンドでの登録
[doskeyコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/doskey)にマクロ名とコマンド名を指定することで使用することでマクロを登録することが可能です。

以下はWindowsのコマンドプロンプトでlsをサポートする場合の例になります。

```
doskey ls=dir $*
```

$*はパラメータを意味して以下のようなコマンド実行が可能になります。

```
ls /s c:\ 
```

$tを使用することで複数のコマンドを実行することが可能になります。

```
doskey prog=echo %ProgramFiles(x86)%$techo %ProgramFiles%
```

登録されたマクロはコマンドプロンプトを終了するまで有効になります。

また先に述べたようにdoskeyコマンドの制約のため、マクロをバッチファイル中で使用することはできませんが、バッチファイルで登録は可能です。

##### ファイルで登録
[doskeyコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/doskey)の/MACROFILEオプションを使用することでファイルからマクロを登録できます。

まず以下のようなファイルを用意します。

```text:macro.txt
ls=dir $*
t=echo test
```

このファイルを用いてファイルを登録するには以下のようにします。

```
doskey /MACROFILE=C:\dev\bat\macro.txt
```


#### マクロの一覧表示
[doskeyコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/doskey)に/macrosオプションを付与することで現在登録中のマクロの一覧を取得できます。

```
REM マクロをすべて表示
doskey /macros
```


#### マクロの削除
Alt+F10で登録されているマクロが削除されます。

### Windows10での新機能
コマンドプロンプトはバージョンアップを続けており、Windows10やWindowsServer2016では新しい機能が色々とサポートされています。

**What's New in the Windows Console in Windows Server 2016 Technical Preview**
https://docs.microsoft.com/en-us/previous-versions/orphan-topics/ws.11/mt427362(v=ws.11)?redirectedfrom=MSDN

**【まとめ】Windows 10で強化／追加されたコマンドプロンプトの機能**
https://www.atmarkit.co.jp/ait/articles/1508/28/news038.html

さらに一部の文字を色を変更して出力することも可能になっています。

```
echo <ESC>[34mtest<ESC>[0m
```
※<ESC>にはESCの文字コード「0x1B」を入力してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/d3dff548-01e4-e5e5-9350-197dcabd06b2.png)

**How to echo with different colors in the Windows command line**
https://stackoverflow.com/questions/2048509/how-to-echo-with-different-colors-in-the-windows-command-line


## バッチファイル
### バッチファイルの実行方法
拡張子batのファイルをエクスプローラーからダブルクリックするか、コマンドプロンプトで以下のように実行するとバッチファイルが実行できます。

たとえば以下のようなバッチファイルが存在します。

```text:sub.bat
echo sub.bat.....
```

これを実行するには以下のようにします。

```
C:\dev\bat\func>C:\dev\bat\func\sub.bat

C:\dev\bat\func>echo sub.bat.....
sub.bat.....

```

バッチファイルを実行すると、バッチファイル内のコマンドがコマンドプロンプトに表示されてしまいます。
バッチファイル内のコマンドをコマンドプロンプトに表示しないようにするには行の先頭に@を付与します。

```text:sub.bat
@echo sub.bat.....
```

このバッチファイルを実行すると@を付けたコマンドがコマンドプロンプトに表示されていないことが確認できます。

```
C:\dev\bat\func>C:\dev\bat\func\sub.bat
sub.bat.....
```

大量のコマンドがある場合、いちいち@を付けるのは面倒です。
この場合、[echoコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/echo)を使用してコマンドエコー機能をオフにします。

```text:sub.bat
@echo off
echo sub.bat.....
```


### バッチファイル中から別のバッチファイルを実行する
バッチファイルの中から別のバッチファイルを実行する場合は[callコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/call)を使用します。

```text:main.bat
@echo off
echo 呼び出し前
call sub.bat
echo 呼び出し後
```

これを実行すると以下のようになります。

```
>main.bat
呼び出し前
sub.bat.....
呼び出し後
```

もし以下のようにcallコマンドを使用せずにバッチを実行した場合、呼び出し元の処理に戻りません。

```text:main.bat
@echo off
echo 呼び出し前
sub.bat
echo 呼び出し後
```

```
>main.bat
呼び出し前
sub.bat.....
```

### バッチファイル内のラベル
バッチファイル内に「:」を使用してラベルを宣言することが可能です。
ラベルには[gotoコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/goto)をジャンプすることができます。

```text:label.bat
@echo off
echo p1
goto label1
echo p2

:label1
echo p3
```

上記のバッチファイルを利用するとgotoで指定したラベルに処理がジャンプすることが可能です。

```
>label.bat
p1
p3
```

指定したラベルは[callコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/call)を使用することで関数のように使用することが可能です。

```text:label2.bat
@echo off
call :label2
echo p4
exit /b

:label2
echo p5
exit /b
```

上記のバッチファイルの実行結果は以下のようになります。

```
>label2.bat
p5
p4
```

p4をエコーする前にlabel2にジャンプしてp5をエコーしていることが確認できます。


### コメントの使用方法
[remコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/rem)を使用することでコメントを使用することができます。


```
REM  コメント1　（コマンドがエコーされます)
@REM コメント2　（コマンドがエコーされません)
```

#### ラベルを利用したコメント
以下のようにラベル（:）を利用したコメントの方法が紹介されている場合があります。

```
::コメント
```

これはあくまでラベルを利用した**トリック**でマイクロソフトで公式のドキュメントで定義されたコメントの仕様ではありません。
たとえば以下のケースではエラーになります。

```
@echo off
IF EXIST C:\ (
	:: Comment line 1
	ECHO Do something
	:: Comment line 2
)
```

下記のページではラベルを使用したコメントについて制限や複数行コメントについてのトリックが述べられています。

**Rob van der Woude's Scripting Pages -Comments-**
https://www.robvanderwoude.com/comments.php

### 別プロセスでバッチファイルを実行する
別プロセスでバッチを実行するには[startコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/start)を利用します。

```
REM 非同期で実行
start cmd.exe /c sleep.bat

REM 同期で実行
start /wait cmd.exe /c sleep.bat
```

### バッチファイルの終了コード
[exitコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/exit_2)を使用することで、バッチファイルの終了コードを指定できます。
終了コードは環境変数ERRORLEVELに格納されます。

```text:test.bat
@echo off
echo main
exit /b 9999
```

```
>test.bat
main

>echo %ERRORLEVEL%
9999
```

/bオプションを付けないで実行するとcmd.exeが終了します。

### バッチファイルのパラメータ
バッチファイルはパラメータを使用することができ、[バッチファイル中に環境変数](#バッチファイルにおける環境変数)を利用してパラメータを参照することができます。

バッチファイル内でパラメータを利用するには%1～%9を使用します。

```text:sub.bat
@echo off
echo sub.bat..... %1 %2 %3
```

バッチファイルをパラメータ付きでよびだすには、パラメータを空白、「,」、「;」で区切ります。

```
>sub.bat abc def jh
sub.bat..... abc def jh

>sub.bat abc,def,jh
sub.bat..... abc def jh

>sub.bat abc;def;jh
sub.bat..... abc def jh
```



### 複数コマンドの実行
バッチファイルやコマンドは[条件付き処理記号](https://msdn.microsoft.com/ja-jp/windows/desktop/cc737438)を使用して実行することができます。


|文字|構文|定義|
|:---|:---|:---|
|& [...]|Command1 &Command2|単一のコマンド ライン上の複数のコマンドを区切るために使います。1 つ目のコマンドが実行された後に、2 つ目のコマンドが実行されます。|
|&& [...]|Command1 &&Command2|&& 記号の前にあるコマンドが正常に終了した場合にのみ、後ろにあるコマンドを実行するために使います。1 つ目のコマンドが実行され、そのコマンドが正常に終了した場合にのみ、2 つ目のコマンドが実行されます。|
|&#124;&#124; [...]|Command1 &#124;&#124; Command2|&#124;&#124; 記号の前にあるコマンドが失敗した場合にのみ、後ろにあるコマンドを実行するために使います。1 つ目のコマンドが実行され、そのコマンドが失敗した場合 (コマンドから返されるエラー コードが 0 よりも大きい場合) にのみ、2 つ目のコマンドが実行されます。|
|( ) [...]|( Command1 & Command2)|複数のコマンドをまとめたり、ネストするときに使います。|

条件付き処理記号の使用例を以下に記述します。

```text:ok.bat
@echo off
echo ok.bat
exit /b 0
```

```text:ng.bat
@echo off
echo ng.bat
exit /b 1
```


```
>REM &の使用例
>call ok.bat & call ng.bat
ok.bat
ng.bat

>call ng.bat & call ok.bat
ng.bat
ok.bat

>REM &&の使用例
>call ok.bat && call ng.bat
ok.bat
ng.bat

>call ng.bat && call ok.bat
ng.bat

>REM ||の使用例
>call ok.bat || call ng.bat
ok.bat

>call ng.bat || call ok.bat
ng.bat
ok.bat

>REM ()の例
>(call ok.bat || call ok.bat) && (call ng.bat)
ok.bat
ng.bat
```


## リダイレクト
[リダイレクト演算子](https://msdn.microsoft.com/ja-jp/windows/desktop/cc772622)を使って、既定の場所から別の場所に、コマンドの入出力ストリームをリダイレクトできます。

### エラー出力
コマンドの出力には標準出力とエラー出力の２種類があります。
多くのコマンドは正常に終了した場合は標準出力に出力し、エラー終了した場合はエラー出力に出力します。

[echoコマンド]()を使用する標準出力に出力しますが、以下のようにすることで標準出力の内容をエラー出力に出力することが可能です。

```
echo error 1>&2
```


### 出力のリダイレクト
ほとんどのコマンドの出力はコマンドプロンプトのウィンドウに送ります。
「>」演算子を使用することで出力をファイルに送ることができます。

以下のコマンドはdirコマンドの出力結果をret.txtファイルに送ります。

```
dir > ret.txt
```

もし存在しないパスを選択してエラーになった場合、dirコマンドはエラー出力に出力しますが、これをファイルに送るには以下のようにします。


```
dir z:\ 2> error.txt
```

ファイルに出力際に「>>」演算子を使用することでファイルの末尾に出力することができます。

```
echo test1 > ret.txt
echo test2 >> ret.txt
```

この結果で出力されるファイルは以下のようになります。

```
test1
test2
```


### 入力のリダイレクト
キーボードからの入力をファイルからリダイレクトするには「<」演算子を使用します。
たとえば[sortコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/sort)はキーボードから入力した内容を昇順に並び替えることができますが、これをファイルから入力するには以下のようにします。

たとえば以下のようなファイル「test.txt」が存在したとして、その内容を並び替かえる例を示します。

```text:test.txt
あがｇ
zZZDfsgsagas
asdfasdf
w235235
12414
agdaga
あああたた
```

```
>sort < test.txt
12414
agdaga
asdfasdf
w235235
zZZDfsgsagas
あああたた
あがｇ
```

### パイプの使用
あるコマンドからの出力を読み取り、別のコマンドの入力に書き込むには「|」演算子を使用します。
たとえば、dirコマンドの出力結果をsortの入力に与えるには以下のようにします。

```
>dir | sort


               2 個のディレクトリ  246,303,686,656 バイトの空き領域
               3 個のファイル                 116 バイト
 C:\dev\bat\redirect のディレクトリ
 ドライブ C のボリューム ラベルは OS です
 ボリューム シリアル番号は ECD8-AD19 です
2019/10/02  17:18                66 test.txt
2019/10/02  18:07                34 error.txt
2019/10/02  18:10                16 ret.txt
2019/10/02  18:14    <DIR>          .
2019/10/02  18:14    <DIR>          ..

```


## 環境変数
すべてのプロセスは[環境変数](https://docs.microsoft.com/en-us/windows/win32/procthread/environment-variables
)を使用できます。
環境変数にはユーザ毎のユーザ環境変数と、すべてのユーザ共通のシステム環境変数の２種類があります。
デフォルトの挙動では子プロセスは親プロセスの環境変数を継承します。


### GUIでの環境変数の確認と設定
コントロールパネルの「システムとセキュリティ」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/470fa667-31ae-fffa-ce0c-8fca9ffed210.png)

「システム」を選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/d0efe04e-6770-a72e-ea49-a958d7208baa.png)

「システムの詳細設定」を選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/64708e4b-95ef-f20a-0b63-2ddfeef03afa.png)

システムのプロパティが表示されるので「環境変数」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/60427840-b412-2ea1-12b2-b94ad30b02d0.png)

ユーザ毎の環境変数とシステムの環境変数が確認と変更が行えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/64dcd89d-2c7e-64b5-63f1-16e5898f50c1.png)

### コマンドプロンプトでの環境変数
#### 環境変数の確認方法
[SETコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/set_1)を実行することで、現在の環境変数を確認できます。

すべての環境変数の一覧を確認するには下記のようなコマンドを実行します。

```
SET
```

特定の環境変数の内容を確認するには引数に環境変数名を指定します。

```
>SET SystemDrive
SystemDrive=C:
```

#### 環境変数の設定方法
現在のプロセス中での環境変数を設定するには[SETコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/set_1)に変数名と値を指定することで可能です。

```
SET test=ABCDE
```

もしコマンドプロンプト中の特殊文字「<、>、| 、＆、^」を使用する場合はエスケープ文字である^を使用するか引用符で囲んで文字列として扱います

```
>set test=a^&n
>set test
test=a&n

>set test="a&n"
>set test
test="a&n"
```

##### 環境変数の削除
設定した環境変数を削除するには以下のように環境変数だけ入力して値を空にします。

```
set test=
```

##### ユーザに環境変数を設定してもらう
ユーザに環境変数を入力させたい場合は以下のように/pオプションを使用します。

```
set /p test=
```

上記のコマンドを入力するとユーザの入力待ちとなり、入力した文字がtest環境変数の値として登録されます。

##### 式を使用して環境変数を設定する
/aオプションを使用することで式を利用して環境変数を設定することが可能です。

```
>set /a test=10+1
11
```

数値が使用できますが、これは10進数ばかりでなく、16進数と8進数の使用が可能です。
負の数は使用可能ですが、小数点を使用することはできません。

```
>set /a test=0x10+1
17
>set /a test=010+1
9
```

また四則演算、論理演算、ビットシフト等がサポートされています。

```
>REM 足し算
>set /a test=1+2
3

>REM 引き算
>set /a test=1-2
-1

>REM 割り算
>set /a test=9/3
3

>REM 掛け算
>set /a test=3*2
6

>REM 剰余の例
>set /a test=9%4
1

>REM インクリメントの例
>set /a test=1
1
>set /a test+=1
2

>REM ビット演算の例
>REM 論理積
>set /a test="0x10&0x11"
16
>REM 論理和
>set /a test="0x10|0x11"
17
>REM 排他的論理和
>set /a test="0x10^0x11"
1

>REM ビットシフト
>set /a test="0x10>>1"
8
>set /a test="0x10<<1"
32
```

#### 環境変数の有効範囲
##### 子プロセスへの環境変数の継承
[startコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/start)でバッチファイルを呼び出し元プロセスの子プロセスとして実行した場合、実行された子プロセスには親プロセスの環境変数を引き継ぎます。

これは以下のようなコマンドで確認できます。

```text:呼び出し元
@echo off
set ver1=testver
set ver1
start /wait cmd /d /c sub0.bat
```

```text:sub0.bat(呼び出し先)
@echo off

echo sub... %ver1%
pause
```

呼び出し元のバッチを実行すると、新しいコマンドプロンプトが開いて下記の内容が表示されます。

```
sub1... testver
```

つまり、呼び出し元の親プロセスで指定した環境変数が子プロセスに反映されていることが確認できます。


##### cmdコマンドでのバッチ実行時の環境変数の検証
[cmdコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cmd)でバッチファイルを呼び出した場合、呼び出し先の環境変数は呼び出し元のものが引き継がれますが、呼び出し先の環境変数は呼び出し元には反映されません。

これは以下のようなコマンドで確認できます。

```text:呼び出し元
@echo off
set ver1=testver
set ver1
echo begin
cmd /d /c sub.bat
echo end
set ver1
```

```text:sub.bat(呼び出し先)
@echo off

echo sub1... %ver1%
set ver1=subver
echo sub2... %ver1%

```

これの結果は以下のようになります。

```text
ver1=testver
begin
sub1... testver
sub2... subver
end
ver1=testver
```

呼びだし元で設定した環境変数は呼び出し先に反映されることが確認できます。
逆に呼び出し先で設定した環境変数は呼び出し元には反映されていないことが確認できます。

##### callコマンドを使用した場合の環境変数の継承
[callコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/call)でバッチファイルを実行した場合、呼び出し元で設定した環境変数は呼び出し先でも反映されます。

これは以下のようなコマンドで確認できます。

```text:呼び出し元
@echo off

set ver1=testver
set ver1
echo begin
call sub.bat
echo end
set ver1
```

呼び出し先は[cmdコマンドでのバッチ実行時の環境変数の検証](#cmdコマンドでのバッチ実行時の環境変数の検証)で使用したものと同じになります。
これの実行結果は以下のようになります。

```text
ver1=testver
begin
sub1... testver
sub2... subver
end
ver1=testver
```

呼び出し元が設定した環境変数が呼び出し先に反映される事が確認できます。
また呼び出し先で設定した環境変数が呼び出し元に反映されることが確認できます。

###### 環境変数の反映を制限する
[setlocalコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/setlocal)を実行することで、バッチファイルの終了時に環境変数の内容を前の状態に戻すことが可能です。

この挙動を確認するには以下を試してみてください。

```text:呼び出し元のサンプル
@echo off
set ver1=testver
set ver1
echo begin
call sublocal.bat
echo end
set ver1
```

```text:sublocal.bat(呼び出し先)
@echo off
setlocal
echo sub1... %ver1%
set ver1=subver
echo sub2... %ver1%
```

これの実行結果は以下のようになります。

```text
ver1=testver
begin
sub1... testver
sub2... subver
end
ver1=testver
```

[setlocalコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/setlocal)がない場合は呼び出し元の環境変数が変更されていましたが、[setlocalコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/setlocal)を実行することで呼び出し元の環境変数が呼び出し先の変更の影響を受けないことを確認できます。

[setlocalコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/setlocal)を実行後に変更された環境変数は[endlocalコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/endlocal)で戻すことが可能です。
[endlocalコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/endlocal)の挙動を確認するには下記を実行してみてください。

```
@echo off
set ver1=testver
set ver1

setlocal
set ver1=testlocal
set ver1
endlocal

set ver1
```

この結果は以下のようになります。

```
ver1=testver
ver1=testlocal
ver1=testver
```

[endlocalコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/endlocal)実行後に環境変数の内容が戻ることが確認できます。

[endlocalコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/endlocal)はバッチファイルの外では有効ではありません。
また、バッチファイルの最後に暗黙的な[endlocalコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/endlocal)が実行されます。


#### 恒久的な環境変数の設定方法
前述のSETコマンドで設定した環境変数はプロセスを再起動すると再使用できません。
環境変数を恒久的に登録する場合は、[SETXコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/setx)を使用します。

ユーザ環境変数を登録するには以下のようにコマンドを実行します。

```
setx test testvalue
```

システム環境変数を登録するには/mオプションを使用します。管理者権限のコマンドプロンプトで下記を実行してください。

```
setx  test testvalue /m
```

なお、SETXコマンドで追加したユーザ環境変数、システム環境変数はコマンドプロンプトを再起動した場合に反映されます。

また、SETXコマンドで環境変数を削除することはできません。

以下のようなコマンドで削除できるという非公式な言説もあります。

```
setx MYVAR ""
```

実際のシステム設定の環境変数情報からは削除されていませんし、公式のドキュメントで消せないと明言しているので、やめましょう。

>You cannot use the setx command to remove values that have been added to the local or system environments.

https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/setx

##### リモートコンピュータの環境変数の設定
setxコマンドはリモートコンピュータ上の環境変数も変更可能です。
これを使用するにはリモートコンピュータ上の「Remote Registry」サービスを有効にする必要があります。

/sオプションでコンピュータ名、/uオプションでユーザ名、/pオプションでパスワードを指定することでリモートコンピュータの環境変数を変更できます。

```
setx /s IEWIN7 /u IEUser /p Passw0rd! test testvalue
```

変更された環境変数はログインをし直すことで有効になります。

なお、「Remote Registry」サービスが起動していない場合、以下のエラーが発生します。

>エラー: 指定された操作を完了できませんでした。

#### 環境変数の展開方法
環境変数名を%で囲うことで変数の値が展開されます。

たとえば[echoコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/echo)を使用して、環境変数の値を展開して表示することが可能です。

```
>echo %SystemDrive%
C:
```

なお、環境変数は大文字、小文字を区別しないため以下のような記載をしても同じ値が取得できます。

```
>echo %SYSTEMDRIVE%
C:
```

なお、この項目についての公式情報は「help set」で確認できます。


##### 環境変数を置換して展開
環境変数の特定の文字を置換して展開することが可能です。
その場合の構文は以下のようになります。

```
%環境変数:置換前=置換後%
```

たとえば環境変数PATHの「c:\」を「d:\」に変換するには以下のようにします。

```
echo %PATH:c:\=d:\%
```

また置換前の最初の一文字アスタリスクを使用することが可能です。
この場合の挙動は最初に見つけた文字だけが置換されます。実例を以下で紹介します。

```
>set test=ABCDEFG_ABCDEFG_ABCDEFG
>REM *を使用しない場合、すべての文字が置換されます。
>echo %test:CD=__%
AB__EFG_AB__EFG_AB__EFG

>REM *を使用した場合、発見した最初の文字のみ置換されます。
>echo %test:*CD=cd%
cdEFG_ABCDEFG_ABCDEFG
```

なお、置換後の文字を空文字とすることで、特定の文字を除去する用途にも使用できます。

##### 環境変数の一部のみ展開

```
>set test=ABCDEFG_ABCDEFG_ABCDEFG
>REM 6文字目から取得する
>echo %test:~5%
FG_ABCDEFG_ABCDEFG

>REM 6文字目から2文字取得する
>echo %test:~5,2%
FG

>REM 最期の5文字を取得する
>echo %test:~-5%
CDEFG

>REM 最期の5文字を除いて取得する
>echo %test:~0,-5%
ABCDEFG_ABCDEFG_AB
```

#### 動的な環境変数
SET によって表示される変数の一覧には表示されない動的な環境変数が存在します。
以下の環境変数は実行時に動的に展開されます。

|変数名|説明|
|:-----|:---|
|%CD%|現在のディレクトリ文字列に展開します。|
|%DATE%|[DATEコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/date)と同じフォーマットで現在の日付に展開します。|
|%TIME%|[TIMEコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/time)と同じフォーマットで現在の時刻に展開します。|
|%RANDOM%|0 から 32767 の間の任意の 10 進数に展開します。|
|%ERRORLEVEL%|現在の ERRORLEVEL の値に展開します。|
|%CMDEXTVERSION%|現在のコマンド プロセッサ拡張機能のバージョン番号に展開します。たとえば「cmd /k xxxx.bat」で起動したコマンドプロンプトでこの環境変数を展開した場合、「cmd /k xxxx.bat」となります。|
|%CMDCMDLINE%|コマンド プロセッサを起動したオリジナル コマンド ラインに展開します。|
|%HIGHESTNUMANODENUMBER%|このコンピューター上の最大の NUMA ノード番号に展開します。|


#### バッチファイルにおける環境変数
バッチファイルの引数は%1～%9で取得できます。
すべてのパラメータを取得するには「%*」を使用します。
%0を指定した場合はバッチファイル名が取得できます。

以下で、その実行例を確認します。

```text:param1.bat
@echo off
echo %*
echo %0
echo %1
echo %2
echo %3
echo %4
echo %5
echo %6
echo %7
echo %8
echo %9
```

```
>param1.bat p1 p2 p3 p4 p5 p6 p7 p8 p9
p1 p2 p3 p4 p5 p6 p7 p8 p9
param1.bat
p1
p2
p3
p4
p5
p6
p7
p8
p9
```

##### 10個以上のパラメータを使用する方法
%には0~9しか指定できません。
10以上のパラメータを使用する場合は[shiftコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/shift)を使用します。

shiftのパラメータとして/2を与えると2番目の引数から右にシフトしていきます。
この実行例は下記のようになります。

```
@echo off
shift /2
echo %*
echo %0
echo %1
echo %2
echo %3
echo %4
echo %5
echo %6
echo %7
echo %8
echo %9
```

```
>param2.bat p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12
p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12
param2.bat
p1
p3
p4
p5
p6
p7
p8
p9
p10
```

##### バッチファイルのパラメータで修飾
バッチファイルの[パラメータは以下の修飾](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/call)を行うことが可能です。

|バッチパラメータ|説明|
|:------|:----------|
|%~1|%1を展開し、周囲の引用符("")を削除します。たとえばパラメータに"abc"を与えた場合、abcに変換されます。|
|%~f1|%1を完全修飾パスに展開します。たとえば相対パスを指定した場合に絶対パスに変換されます|
|%~d1|%1をドライブ文字のみに展開します。|
|%~p1|%1をパスのみに展開します。|
|%~n1|%1をファイル名のみに展開します。|
|%~x1|%1をファイル名拡張子のみに展開します。|
|%~s1|%1をショートネームのみを含む完全修飾パスに展開します。|
|%~a1|%1に存在するファイルを指定した場合、そのファイル属性に展開します。|
|%~t1|%1に存在するファイルを指定した場合、ファイルの更新日時刻に展開します。|
|%~z1|%1に存在するファイルを指定した場合、ファイルのサイズに展開します。|
|%~$PATH:1|PATH環境変数にリストされているディレクトリを検索し、%1で指定したファイルを最初に見つけたディレクトリのフルパスに展開します。環境変数名が定義されていないか、検索でファイルが見つからない場合、この修飾子は空の文字列に展開されます。|

これらの修飾子は組み合わせて使用できます。
たとえば「%~dp0」と記載した場合、バッチファイルの親ディレクトリに展開できます。

動的環境変数を上書きするのは避けてください。
たとえば、以下のように環境変数のERRORLEVELを書き換えても実際の最後に実行したコマンドのエラーコードを書き換えることはできませんし、環境変数を上書きすることで不整合が生じます。

```
rem this next command sets the error level to zero

CMD /C EXIT 0

set ERRORLEVEL=1

if ERRORLEVEL 1 echo Does this print?
```

[ERRORLEVEL is not %ERRORLEVEL%](https://devblogs.microsoft.com/oldnewthing/20080926-00/?p=20743)より


もしERRORLEVELをクリアしたい場合は任意の成功するコマンドを実行する必要があります。

例：

```
>cmd /c exit /b 0
>ver >nul
```

https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cmd

#### 遅延環境変数の展開
環境変数は実行時には展開されません。
たとえば以下のバッチファイルを実行したとします。

```
@echo off
set VAR=before
if "%VAR%" == "before" (
    echo if1.....
    set VAR=after
    if "%VAR%" == "after" echo If 2...
    echo %VAR%
)
```

このバッチファイルの意図としては２つのIF文が共に真になる意図ですが、実際の結果は以下のようになります。

```
>tien.bat
if1.....
before
```

1つ目のIFの内での環境変数の設定した内容が反映されていないことがわかります。
実行時に環境変数を展開するためには感嘆符(!)を使用して遅延環境変数を使用する必要があります。

```
@echo off
set VAR=before
if "%VAR%" == "before" (
    echo if1.....
    set VAR=after
    if "!VAR!" == "after" echo If 2...
    echo !VAR!
)
```

既定の挙動では遅延環境変数は展開されません。
これを有効にするには２種類の方法があります。

###### cmd実行時に/vオプションを利用する
[cmdマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cmd)実行時に/vオプションを使用することで遅延環境変数を展開可能です。

```
>cmd /v:on /c tien2.bat
if1.....
If 2...
after
```

##### setlocalでENABLEDELAYEDEXPANSIONを指定する
[setlocalコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/setlocal)にenabledelayedexpansionを指定することで遅延変数の展開が可能になります。
この設定はcmdのパラメータより優先されます。

```
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set VAR=before
if "%VAR%" == "before" (
    echo if1.....
    set VAR=after
    if "!VAR!" == "after" echo If 2...
    echo !VAR!
)
```

このバッチファイルの実行結果は下記のようになります。

```
>tien3.bat
if1.....
If 2...
after
```

## 分岐
[IFコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/if)を使用することで分岐を記述できます。

### ERRORLEVELの分岐
「IF ERRORLEVEL 番号」と記載することで最後のプログラムの実行で指定された番号以上の終了コードが返されたときに、条件が真になるように指定します。

```
>cmd /c exit 1
>IF ERRORLEVEL 1 (echo NG) ELSE (echo OK)
NG
>cmd /c exit 0
>IF ERRORLEVEL 1 (echo NG) ELSE (echo OK)
OK
```

ERRORLEVELの分岐として環境変数のERRORLEVELを使用することができます。
この場合は以下のいずれかの演算子を指定する必要があります。

 - EQU - 等しい
 - NEQ - 等しくない
 - LSS - より小さい
 - LEQ - 以下
 - GTR - より大きい
 - GEQ - 以上

```
>cmd /c exit 1
>IF %ERRORLEVEL% equ 0 (echo OK) ELSE (echo NG)
NG
>cmd /c exit 0
>IF %ERRORLEVEL% equ 0 (echo OK) ELSE (echo NG)
OK
```

### ファイルの存在チェック
「IF EXIST ファイル名」と記載することでファイルの存在をチェックすることができます。

```
>IF EXIST 存在するファイル.txt (echo 真) ELSE (echo 偽)
真
>IF NOT EXIST 存在するファイル.txt (echo 真) ELSE (echo 偽)
偽
>IF EXIST 存在しない.txt (echo 真) ELSE (echo 偽)
偽
>IF NOT EXIST 存在しない.txt (echo 真) ELSE (echo 偽)
真
```

### 環境変数の存在チェック
「IF DEFINED 環境変数名」と記載することで環境変数の存在をチェックすることができます。

```
>set test=
>if DEFINED test (echo 真) ELSE (echo 偽)
偽

>if NOT DEFINED test (echo 真) ELSE (echo 偽)
真

>set test=abc
>if DEFINED test (echo 真) ELSE (echo 偽)
真

>if NOT DEFINED test (echo 真) ELSE (echo 偽)
偽
```

### 文字列の比較
==演算子を使用して文字列の比較が可能です。
既定では大文字小文字を区別しますが、/iオプションを使用することで大文字小文字を区別しないで比較をします。

```
>set test=abc
>IF %test% ==abc (echo 真) ELSE (echo 偽)
真
>IF %test% ==ABC (echo 真) ELSE (echo 偽)
偽
>IF /I %test% ==ABC (echo 真) ELSE (echo 偽)
真
```

以下のいずれかの演算子を使用して比較することも可能です。

 - EQU - 等しい
 - NEQ - 等しくない
 - LSS - より小さい
 - LEQ - 以下
 - GTR - より大きい
 - GEQ - 以上

```
>set test=abc
>IF  %test% equ abc (echo 真) ELSE (echo 偽)
真
>IF  %test% equ ABC (echo 真) ELSE (echo 偽)
偽
>IF NOT  %test% neq abc (echo 真) ELSE (echo 偽)
真
>IF NOT  %test% neq ABC (echo 真) ELSE (echo 偽)
偽
>IF /I  %test% equ ABC (echo 真) ELSE (echo 偽)
真
```

EQUなどの演算子を使用すると数値としても使用することが可能です。

```
>set num=10
>IF %num% GEQ 9 (echo 真) ELSE (echo 偽)
真

>IF %num% GEQ 10 (echo 真) ELSE (echo 偽)
真

>IF %num% GEQ 11 (echo 真) ELSE (echo 偽)
偽

>IF %num% LEQ 9 (echo 真) ELSE (echo 偽)
偽

>IF %num% LEQ 10 (echo 真) ELSE (echo 偽)
真

>IF %num% LEQ 11 (echo 真) ELSE (echo 偽)
真
```

## 繰り返し
[forコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/for)を使用することで繰り返し処理を記述できます。

### セットの繰り返し
> for {%%&#124;%}<変数名> in (セット) do コマンド　[コマンドライン引数]

in句の後で指定したセットを繰り返すことが可能です。
コマンドラインで実行する場合の例は以下のようになります。

```
>for %a in (ab,cd,ef,eataeta) do @(echo %a)
ab
cd
ef
eataeta
```

IN句のセットの書き方は以下のようにも記載できます。

```
>for %a in (ab;cd;ef;eataeta) do @(echo %a)
>for %a in (ab cd ef eataeta) do @(echo %a)
```

バッチファイルを使用する場合は以下のようになります。

```text:dataset.bat
@echo off
for %%a in (ab,cd,ef,eataeta) do (
    echo %%a
)
```

```
>dataset.bat
ab
cd
ef
eataeta
```

### ワイルドカードの使用
セットにはワイルドカードを指定してファイルを取得することができます。
バッチファイルで使用する場合、変数には「%%」を指定してください。

```
>for %a in (*.txt) do @(echo %a)
error.txt
list.txt
result.txt
ret.txt

>for %a in (c:\dev\bat\*) do @(echo %a)
c:\dev\bat\init.bat
c:\dev\bat\initCur.bat
c:\dev\bat\t.bat
c:\dev\bat\test.bat
c:\dev\bat\testchoise.bat
c:\dev\bat\testLs.bat
c:\dev\bat\testLs2.bat
```

既定ではディレクトリの取得はできません。


### ディレクトリの取得
/dオプションを使用するとディレクトリを取得することができます。
バッチファイルで使用する場合、変数には「%%」を指定してください。

```
>for /d %a in (c:\dev\bat\*) do @(echo %a)
c:\dev\bat\bunki
c:\dev\bat\file
c:\dev\bat\func
c:\dev\bat\redirect
c:\dev\bat\run
c:\dev\bat\test
c:\dev\bat\test2
c:\dev\bat\ver
```

### ファイルを再帰的に取得
/rオプションを使用すると指定したディレクトリを再帰的に探査可能です。
バッチファイルで使用する場合、変数には「%%」を指定してください。

```
>for /r c:\dev\ %a in (*.txt) do @(echo %a)
c:\dev\akanechan_powerpoint\Slide1_0.txt
c:\dev\akanechan_powerpoint\Slide1_1.txt
c:\dev\akanechan_powerpoint\Slide1_2.txt
c:\dev\bat\bunki\error.txt
c:\dev\bat\bunki\list.txt
c:\dev\bat\bunki\result.txt
c:\dev\bat\bunki\ret.txt
c:\dev\bat\file\1.txt
c:\dev\bat\file\2.txt
```

### 変数の展開の修飾子
ループで使用する変数については以下の修飾子が使用できます。
以下の説明は%Iを変数とした場合の修飾子の例になります。

```
    %~I         - すべての引用句 (") を削除して、%I を展開します。
    %~fI        - %I を完全修飾パス名に展開します。
    %~dI        - %I をドライブ文字だけに展開します。
    %~pI        - %I をパス名だけに展開します。
    %~nI        - %I をファイル名だけに展開します。
    %~xI        - %I をファイル拡張子だけに展開します。
    %~sI        - 展開されたパスは短い名前だけを含みます。
    %~aI        - %I をファイルの属性に展開します。
    %~tI        - %I ファイルの日付/時刻に展開します。
    %~zI        - %I ファイルのサイズに展開します。
    %~$PATH:I   - PATH 環境変数に指定されているディレクトリを
                   検索し、最初に見つかった完全修飾名に %I を
                   展開します。
                   環境変数名が定義されていない場合、または検索
                   してもファイルが見つからなかった場合は、この
                   修飾子を指定すると空の文字列に展開されます。
```

使用例は以下のようになります。

```
>for %I in (*.txt) do @echo %~fI %~dI %~pI %~nI %~xI %~sI %~aI %~tI  %~zI
C:\dev\bat\bunki\error.txt C: \dev\bat\bunki\ error .txt C:\dev\bat\bunki\error.txt --a-------- 2019/09/28 16:02  0
C:\dev\bat\bunki\list.txt C: \dev\bat\bunki\ list .txt C:\dev\bat\bunki\list.txt --a-------- 2019/09/28 02:50  81
C:\dev\bat\bunki\result.txt C: \dev\bat\bunki\ result .txt C:\dev\bat\bunki\result.txt --a-------- 2019/09/28 03:59  17
C:\dev\bat\bunki\ret.txt C: \dev\bat\bunki\ ret .txt C:\dev\bat\bunki\ret.txt --a-------- 2019/09/28 16:49  3
C:\dev\bat\bunki\te st.txt C: \dev\bat\bunki\ te st .txt C:\dev\bat\bunki\te st.txt --a-------- 2019/10/02 21:38  92
C:\dev\bat\bunki\test.txt C: \dev\bat\bunki\ test .txt C:\dev\bat\bunki\test.txt --a-------- 2019/10/02 21:38  92
```

### 値の範囲を繰り返す
/Lオプションを使用することで値の範囲を指定することができます。
書式としては以下のようになります。

>for /l {%%&#124;%}<変数名> in (開始値,増分,終了値) do コマンド　[コマンドライン引数]

ループカウンタに使用する変数はコマンドラインで実行する場合は「%変数名」となり、バッチファイル中で使用する場合は「%%変数名」となります。
in句の後にはループカウンタの開始値、増分、終了値の順番で指定します。


コマンドプロンプトで実行する場合の例は以下のようになります。

```
>for /L %a in (0, 2, 9) do @(echo %a)
0
2
4
6
8
```

バッチファイルの場合は以下のようになります。

```text:loop.bat
@echo off
for /L %%a in (0, 2, 9) do (
    echo %%a
)
```

```
>loop.bat
0
2
4
6
8
```

### ファイルの解析
/Fオプションを使用することでファイルの内容を1行づつ解析できます。
たとえば以下のようなファイルが存在するとします。

```text:test.txt
1234,5678,9abc
2345,6789,abcd
3456,789a,bcde
;aaa,bbb,cccコメント
ああああ,いいい,ううう
```

これを一行づつ処理するには以下のようにします。

```
>FOR /F %a in (test.txt) do @echo %a
1234,5678,9abc
2345,6789,abcd
3456,789a,bcde
ああああ,いいい,ううう
```

一行づつechoコマンドが実行されます。
ただし、;で開始している行はコメント行として処理されてループの対象となりません。
もしバッチファイル内で使用するには%aを%%aと置き換えます。

/Fオプションの後に以下のキーワードを使用することが可能です。

 - eol
 - skip
 - usebackq
 - delims
 - tokens

#### eolキーワード
eolで指定した1文字がコメント行として解釈されます。
eolを指定しない場合は「;」で開始される行がコメント行として処理されます。

```
>FOR /F "eol=1" %a in (test.txt) do @echo %a
2345,6789,abcd
3456,789a,bcde
;aaa,bbb,cccコメント
ああああ,いいい,ううう
```

#### skipキーワード
skip行で指定した行数を飛ばしてループの対象とします。
たとえば以下の場合、先頭の2行をスキップして行をループします。

```
>FOR /F "eol=# skip=2" %a in (test.txt) do @echo %a
3456,789a,bcde
;aaa,bbb,cccコメント
ああああ,いいい,ううう
```

#### usebackqキーワード
セットに指定するファイル名に二重引用符で囲むことを許可します。
これにより空白のファイル名を指定できます。

```
>FOR /F "usebackq" %a in ("te st.txt") do @echo %a
1234,5678,9abc
2345,6789,abcd
3456,789a,bcde
ああああ,いいい,ううう
```
#### delims、tokensキーワード
delimsキーワードは区切り文字を指定できます。デフォルトはスペースまたはTabになります。
tokensキーワードはどのトークンをループにわたすかを指定できます。

たとえば「,」区切って1つ目と3つ目を表示するには以下のように指定します。

```
>FOR /F "delims=, tokens=1,3" %a in (test.txt) do @echo %a %b
1234 9abc
2345 abcd
3456 bcde
ああああ ううう
```

たとえば「,」区切って2つ目～3つ目を表示するには以下のように指定します。

```
>FOR /F "delims=, tokens=2-3" %a in (test.txt) do @echo %a %b
5678 9abc
6789 abcd
789a bcde
いいい ううう
```

tokensに*を指定することで、解析される最後のトークンの後の行に残っているテキストを受け取ります。

```
>FOR /F "delims=, tokens=1,*" %a in (test.txt) do @echo %a %b
1234 5678,9abc
2345 6789,abcd
3456 789a,bcde
ああああ いいい,ううう
```



## コンソールの操作
### コンソールのクリア
[clsコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cls)を使用することでコンソールの内容をクリアできます。

### タイトルの変更
[titleコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/title_1)を使用することでコマンドプロンプトのタイトルを変更できます。

```
title タイトルの変更
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/c2ce0f12-402a-3468-0beb-b91f03e2d8dd.png)

### ポーズコマンド
[pauseコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/pause)を使用することでキーボードの入力待ちが行えます。

```
>pause
続行するには何かキーを押してください . . .
```

### ユーザ入力
[choiceコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/choice)を使用することでユーザ入力を行えます。
ユーザが選択した結果は%ERRORLEVEL%に格納されます。

```
>choice /m 選択してください
選択してください [Y,N]?Y

>echo %ERRORLEVEL%
1

>choice /m 選択してください
選択してください [Y,N]?N

>echo %ERRORLEVEL%
2
```

既定ではY,Nの選択になりますが、/cオプションを使用することで選択項目をカスタマイズできます。

```
>choice /c ync1234567890 /m 選択してください
選択してください [Y,N,C,1,2,3,4,5,6,7,8,9,0]?2

>echo %ERRORLEVEL%
5
```

## ファイル操作
### カレントディレクトリの設定
カレントディレクトリの移動には２種類の方法があります。

#### cdまたはchdirによるカレントディレクトリの変更
[cdコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cd)または[chdirコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/chdir_1)でカレントディレクトリを変更します。

ドライブを変更する場合は/dオプションを使用してください。

```text
cd c:\
chdir c:\dev
chdir /d e:\
cd /d c:\
```



#### スタックを使用したカレントディレクトリの変更
[pushdコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/pushd)と[popdコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/popd)を使用することでスタックを使用してカレントディレクトリを変更できます。
これを呼び出し先のバッチファイルで使用することで呼び出し先で変更したカレントディレクトリを呼び出し元のカレントディレクトリに戻すことが可能になります。

以下に[pushdコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/pushd)と[popdコマンド]の実行例を記述します。

```
c:\>pushd c:\dev

c:\dev>pushd c:\dev\bat

c:\dev\bat>popd

c:\dev>popd
```

pushdで変更したディレクトリがpopdで元に戻ることが確認できると思います。

### 空ファイルの作成
[copyコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/copy)を使用してnulでファイルを作成すると空ファイルが作成できます。

すでにあるファイルを空にする場合は/yオプションを使用して強制的に上書きします。

```
copy nul test.txt
copy /y nul test.txt
```

### ディレクトリの作成
[mdコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/md)または[mkdirコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/mkdir)でディレクトリを作成します。

中間ディレクトリがない場合は作成されます。
すでに存在するディレクトリを指定した場合はエラーとなります。

```
md test\test\test
mkdir test2\test\test
```

### リンクの作成
[mklinkコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/mklink)を使用してシンボリックリンク、ハードリンク、ジャンクションが作成可能です。

これらの違いは下記を参照してください。

**Windowsのシンボリックリンクとジャンクションとハードリンクの違い**
https://www.atmarkit.co.jp/ait/articles/1306/07/news111.html

#### シンボリックリンクの作成
ディレクトリのシンボリックリンクを作成する場合は/Dオプションを使用してください。
またディレクトリのシンボリックリンクを作成する場合は管理者権限で実行する必要があります。

```
mklink slink_a.txt c:\dev\ps\file\link\a.txt
mklink sdir c:\dev\ps\file\link\sub2 /D
```

#### ハードリンクの作成
ハードリンクを作成するには/hオプションを使用してください。

```
mklink /H hardlink_a.txt c:\dev\ps\file\link\a.txt
```

#### ジャンクションの作成
/jオプションを使用することでジャンクションを作成できます。

```
mklink /j junction_dir c:\dev\ps\file\link\sub1
```

### ファイルとディレクトリの列挙
#### 一覧表示
[dirコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/dir)を使用するとサブディレクトリの一覧を表示します。

ディレクトリを指定する場合、*または?のワイルドカードが使用できます。*は任意の文字列、?は任意の一文字以下をあらわします。
たとえばディレクトリは以下に以下のファイルが存在したとします。

 - abcde.txt
 - abcd.txt
 - abc.txt
 - ab.txt
 - a.txt
 - a.text
 - .txt

「*.txt」を指定して検索した場合以下のファイルが列挙されます。

 - abcde.txt
 - abcd.txt
 - abc.txt
 - ab.txt
 - a.txt

「????.txt」を指定した場合以下のファイルが列挙されます。

 - abcd.txt
 - abc.txt
 - ab.txt
 - a.txt

/aオプションを使用することで隠しファイルやシステムファイルも表示可能になります。
/sオプションを使用することでサブディレクトリの内容を表示します。

コマンドの使用例は以下のようになります。

```
REM 拡張子がtxtのファイルを列挙
dir C:\dev\ps\file\link\*.txt

REM 拡張子がtxtのファイルを列挙
dir C:\dev\ps\file\link\????.txt

REM 隠しファイル含めて列挙
dir C:\dev\ps\file\link\sub1 /a

REM サブディレクトリを列挙
dir C:\dev\ps\file\link\ /s
```

#### ツリー構造での表示
[tree](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/tree)コマンドを使用することでディレクトリ構造をツリー構造で表示します。
/fオプションを使用することでファイルも表示可能ですが、隠しファイルを表示することはできません。

```
>tree /f c:\dev\bat\file
ディレクトリー パスの一覧:  ボリューム OS
ボリューム シリアル番号は ECD8-AD19 です
C:\DEV\BAT\FILE
│  .txt
│  a.text
│  a.txt
│  ab.txt
│  abc.txt
│  abcd.txt
│  abcde.txt
│
└─sub1
        test.txt
        test2.txt
```


### ファイルの検索
[whereコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/where_1)を使用することで指定したファイルのパスを検索できます。

一致するファイルの検索パターンにはワイルドカード(*と?)が使用できます。ワイルドカードの挙動は[dirコマンドで説明した挙動](#一覧表示)と同じです。ディレクトリを指定するか、環境変数を指定することが可能ですが、いずれも指定せずに検索した場合はカレントディレクトリとPATH環境変数で指定したディレクトリを検索します。
/Rオプションと組み合わせてディレクトリを指定することで特定のディレクトリ以下のサブディレクトリをすべて検索します。
隠しファイルが存在する場合、それも検索対象となります。

```
REMカレントディレクトリと環境変数PATH以下でtxt拡張子のファイルを検索する
where *.txt

REM環境変数Publicのディレクトリのファイルを検索する
where $PUBLIC:*.*

REM 特定のディレクトリを再帰的に検索して*.txtにマッチするファイルを検索する
where -R C:\dev\ps\file\link\sub1 *.txt

```

### ファイルの削除
ファイルの削除には[delコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/del)を使用します。
削除対象のファイルはワイルドカード(*と?)が使用できます。ワイルドカードの挙動は[dirコマンドで説明した挙動](#一覧表示)と同じです。
ゴミ箱には送らない、取り返しのつかない操作なので十分に注意して使用してください。

```
REM カレントディレクトリのtxt拡張子を削除する
del *.txt

REM 特定ディレクトリのtxt拡張子を削除する
del c:\dev\bat\*.txt
```

規定の動作では隠しファイルや読み取り専用ファイルを削除できません。
/fと/aオプションを付与して削除してください。

```
del /a /f *.txt
```

/pオプションを使用することで確認メッセージを表示可能になります。

```
>del /p  *.txt
C:\dev\bat\file\ab.txt を削除しますか (Y/N)? n
C:\dev\bat\file\abc.txt を削除しますか (Y/N)? n
C:\dev\bat\file\abcd.txt を削除しますか (Y/N)? n
C:\dev\bat\file\abcde.txt を削除しますか (Y/N)? n
C:\dev\bat\file\test.txt を削除しますか (Y/N)? n
C:\dev\bat\file\test2.txt を削除しますか (Y/N)? n
```

### ディレクトリの削除
ディレクトリの削除には[rmdirコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/rmdir)または[rdコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/rd)を使用します。ゴミ箱には送らない、取り返しのつかない操作なので十分に注意して使用してください。

/sオプションを指定することでサブディレクトリを含めて削除可能です。この際確認メッセージが表示されますが、確認メッセージを表示しないようにするには/qオプションを使用します。

```
>rmdir /s sub2
sub2、よろしいですか (Y/N)? y

>rmdir /s /q sub2
```

削除対象のディレクトリをカレントディレクトリとして使用しているプロセスがある場合以下のようなメッセージが表示されます。

```
>rmdir /s /q c:\dev\bat\file\sub2
プロセスはファイルにアクセスできません。別のプロセスが使用中です。
```


### ファイルの改名
ファイルまたはディレクトリの改名には[renコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/ren)または[renameコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/rename)を使用します。

ファイルの改名にはワイルドカードを使用することが可能です。ワイルドカードの挙動は[dirコマンドで説明した挙動](#一覧表示)と同じです。ただし、隠しファイルは対象となりません。


```
REM c:\dev\bat\file\sub1ディレクトリをc:\dev\bat\file\sub1_renamedに変更します。
ren c:\dev\bat\file\sub1 sub1_renamed

REM 拡張子txtをdocに変更します。
ren *.txt *.doc
```


### ファイルのコピー
[copyコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/copy)を使用してコピー元のファイルを指定のディレクトリまたはファイルにコピーします。

```
REM ファイルを指定してコピー
>copy ab.doc z.doc
        1 個のファイルをコピーしました。

REM directoryを指定してコピー
>copy *.doc C:\dev\bat\file\sub2
ab.doc
abc.doc
abcd.doc
abcde.doc
test.doc
        5 個のファイルをコピーしました。
```

### ディレクトリのコピー
[xcopyコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/xcopy)を使用してディレクトリのコピーが可能です。

/sオプションでサブディレクトリのコピーも可能です。
/eオプションで空のサブディレクトリもコピーします。
/hオプションで隠しファイルのコピーも行います。デフォルトでは隠しファイルをコピーしません。
/kオプションでコピー元の読み取り専用属性をコピー先に反映させます。デフォルトでは反映されません。

```
REM 隠しファイルはコピーされない
xcopy c:\dev\bat\file\sub c:\dev\bat\file\target /s /e

REM 隠しファイルはコピーされる
xcopy c:\dev\bat\file\sub c:\dev\bat\file\target /s /e /h
```

コピーの挙動としては以下のようになります。

```
target 
  sub の子要素1
    孫要素
  sub の子要素2
```


### ファイル/ディレクトリの移動
[moveコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/move)を使用してファイルまたはディレクトリを移動します。
/yオプションを使用することで移動先がすでに存在する場合に確認メッセージを表示しないで上書きしません。

```
>move ab.doc xxx.doc
        1 個のファイルを移動しました。

>move /y abcd.doc abc.doc
        1 個のファイルを移動しました。

>move sub2 sub3
        1 個のディレクトリを移動しました。
```

### ファイルの内容表示
[typeコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/type)または[moreコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/more)を使用することでファイルの内容を表示します。

[typeコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/type)は一度にすべて表示します。
[moreコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/more)は１ページづつ表示されます。

```
>type sjis.txt

>more sjis.txt
````

デフォルトのコードページ以外（日本語OSの場合はcp932)のファイルとUNICODE以外のテキストファイルを表示する場合は[chcpコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/chcp)を使用します。

```
REM BOMなしのUTF8を表示します。
>chcp 65001
>type utf8.txt
```

なお古いバージョンのWindowsだとフォントの都合で表示されません。cp932でフォントをMSゴシックを選択していれば表示される場合もありますが、正直、すべての環境での挙動が安定していないように見えます。
またchcpを使用した場合、moreコマンドを使用すると文字化けします。

SJISやUNICODE以外の文字コードを扱う場合は、[PowerShellでも使った方が楽](https://qiita.com/mima_ita/items/ae31f3a19389e69b307f#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E5%86%85%E5%AE%B9%E8%A1%A8%E7%A4%BA)だと思います。

### ファイルの連結
[typeコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/type)を使用するか、[copyコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/copy)を使用します。

たとえば以下のような２ファイルがあるとします。

```1.txt
あいうえお
かきくけこ
さしすせそ
```

```2.txt
たちつてと
なにぬねの
```

1.txtの末尾に2.txtを結合するには以下のようにします。

```
REM 1.txtの末尾に2.txtが追記
type 2.txt >> 1.txt

REM 1.txtの後に2.txtが追記された結果がresult.txtに書き込まれる。
copy /b 1.txt+2.txt result.txt

```

copyコマンドの/bオプションはバイナリでの連結を意味します。これを付与しない場合、末尾に0x1A(CTRL+Z)が付与されます。



### ファイルの属性変更
[attribコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/attrib)を使用することでファイルの属性を変更できます。

```
REM 読み取り専用にする
attrib result.txt +R

REM 読み取り専用を解除
attrib result.txt -R

REM 読み取り専用、隠しファイル、システムファイルとする
attrib result.txt +R +H +S
```
 
### ファイルの所有者変更
管理者権限で[icacls コマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/icacls)を使用することでファイルの所有者を変更可能です。

```
icacls result.txt /setowner NOTE-MAIN\mima
```



### ファイル中の文字検索
[findコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/find)または[findstrコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/findstr)を使用します。

```
>find "あい" *.txt

---------- 1.TXT
あいうえお

---------- 2.TXT

---------- RESULT.TXT
あいうえお
```

サブディレクトリも検索する場合はfindstrコマンドの/sオプションを使用します。

```
>findstr /s "あい" *.txt
1.txt:あいうえお
result.txt:あいうえお
sub\1.txt:あいうえお
```

### ファイルの比較
[compコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/comp)または、[fcコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/fc)を使用します。

#### compコマンド
[compコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/comp)はバイナリでファイルを比較します。
/mオプションを付けない場合、続けてファイルを比較するようなプロンプトを表示します。
ファイルの比較結果が同一の場合、ERRORLEVELは0となります。
ファイルの比較結果が異なる場合、ERRORLEVELは1となります。
構文エラーがある場合、ERRORLEVELは2となります。


```
REM ファイルが等しい場合はERRORLEVELは0となります。
>comp /m 1.txt 1.txt
1.txt と 1.txt を比較しています...
ファイルに違いはありません

>echo %ERRORLEVEL%
0

REM ファイルサイズが異なる場合
>comp /m 1.txt 4.txt
1.txt と 4.txt を比較しています...
ファイルのサイズが違います。

>echo %ERRORLEVEL%
1

REM ファイルサイズが等しくて内容が異なる場合
>comp /m 1.txt 3.txt
1.txt と 3.txt を比較しています...
OFFSET 11 で比較エラーがあります
ファイル1 = AD
ファイル2 = AF
OFFSET 1B で比較エラーがあります
ファイル1 = B5
ファイル2 = A2

>echo %ERRORLEVEL%
1

```

#### fcコマンド
[fcコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/fc)はASCII比較またはバイナリーでの比較が行えます。

ファイルの比較結果が同一の場合、ERRORLEVELは0となります。
ファイルの比較結果が異なる場合、ERRORLEVELは1となります。
構文エラーがある場合、ERRORLEVELは2となります。

/Bオプションを使用することでバイナリの比較を実行します。
/Uオプションを使用することでUNICODEで比較を実行します。
ASCII比較時に/Nオプションを使用することで行番号を表示します。

```
REM 相違点のあるファイルをASCIIで比較
>fc /N  fc1sjis.txt fc2sjis.txt
ファイル fc1sjis.txt と FC2SJIS.TXT を比較しています
***** fc1sjis.txt
    4:  あいうえお
    5:  かきくけこ
    6:  a
***** FC2SJIS.TXT
    4:  あいうえお
    5:  かきけっけけこ
    6:  a
*****

***** fc1sjis.txt
   10:  35235235235
   11:  3252353efwrwerwrwr
***** FC2SJIS.TXT
   10:  35235235235
   11:  ああああ
   12:  3252353efwrwerwrwr
*****


>echo %ERRORLEVEL%
1

REM 相違点のないファイルを比較
>fc /N  fc1sjis.txt fc1sjis.txt
ファイル fc1sjis.txt と FC1SJIS.TXT を比較しています
FC: 相違点は検出されませんでした

>echo %ERRORLEVEL%
0

REM バイナリモードで比較を行う
>fc /B  1.txt 3.txt
ファイル 1.txt と 3.TXT を比較しています
00000011: AD AF
0000001B: B5 A2

>echo %ERRORLEVEL%
1

C:\dev\bat\file>fc /B  1.txt 4.txt
ファイル 1.txt と 4.TXT を比較しています
00000010: 82 61
00000011: AD 82
REM 略
00000021: BB 82
FC: 4.TXT は 1.txt より長いファイルです

>echo %ERRORLEVEL%
1

REM UNICODEのファイルを比較する
>fc /N /U  fc1unicode.txt fc2unicode.txt
ファイル fc1unicode.txt と FC2UNICODE.TXT を比較しています
***** fc1unicode.txt
    4:  あいうえお
    5:  かきくけこ
    6:  a
***** FC2UNICODE.TXT
    4:  あいうえお
    5:  かきけっけけこ
    6:  a
*****

***** fc1unicode.txt
   10:  35235235235
   11:  3252353efwrwerwrwr
***** FC2UNICODE.TXT
   10:  35235235235
   11:  ああああ
   12:  3252353efwrwerwrwr
*****

```

## レジストリの操作
レジストリの操作は[regコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/reg)を使用しておこないます。

レジストリの詳細は下記を参照してください。
https://qiita.com/mima_ita/items/ff656af8e4b56ed17a53

### レジストリの参照
[regコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/reg)の[query](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/reg-query)を用いることでレジストリの参照が可能です。

/vオプションを使用することで値を指定してレジストリの内容を表示します。
/sオプションを使用することで再帰的にレジストリキーの内容を表示します。

```
REM レジストリ―キーの内容を確認する
>reg query HKCU\test\a\b\

HKEY_CURRENT_USER\test\a\b
    (既定)    REG_SZ
    data    REG_SZ    test2
    test    REG_EXPAND_SZ    %PATH%

REM 特定のレジストリ―キーの値の内容を確認する
>reg query HKCU\test\a\b\ /v test

HKEY_CURRENT_USER\test\a\b
    test    REG_EXPAND_SZ    %PATH%

REM レジストリキーを再帰的に確認する
>reg query HKCU\test\ /s

HKEY_CURRENT_USER\test\a
    x    REG_SZ    abc

HKEY_CURRENT_USER\test\a\b
    (既定)    REG_SZ
    data    REG_SZ    test2
    test    REG_EXPAND_SZ    %PATH%

```

リモートコンピュータ側のRemote Registryサービスを起動することでコンピュータ名を指定してレジストリの参照が行えます。

```
>reg query \\IEWin7\HKLM\SOFTWARE
```

### レジストリの登録
[regコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/reg)の[add](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/reg-add)を用いることでレジストリの登録が可能です。

レジストリキーを登録する場合は以下を実行します。

```text
reg add HKCU\test\a\b
```

指定したキーの途中が存在しない場合でもエラーとならず作成されます。
またすでにキーが存在する場合は下記の確認メッセージが表示されます。

```
値  は存在します。上書きしますか? (Yes/No)
```

レジストリの値を追加するには以下のようになります。

```
reg add HKCU\test\a\b /v data /t REG_SZ /d test2
```

指定したキーが存在しない場合でもエラーとならず作成されます。
またすでにキーが存在する場合は確認メッセージが表示されます。

リモートコンピュータ側のRemote Registryサービスを起動することでコンピュータ名を指定してレジストリの追加が行えます。

```
>reg add \\IEWin7\HKLM\SOFTWARE\test\a\b /v data /t REG_SZ /d test2
```

### レジストリのエクスポート
[regコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/reg)の[export](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/reg-export)を用いることでレジストリの内容をファイルにエクスポートすることが可能です。

```
reg export HKCU\test\ export.reg
```

### レジストリのインポート
[regコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/reg)の[import](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/reg-import)を用いることでファイルの内容をレジストリにインポートすることが可能です。

```
reg import  export.reg
```

## スリープ処理
コマンドプロンプトやバッチファイルでスリープ処理を入れる方法は色々あります。

 - timeoutコマンド
 - pingコマンド
 - powershellでスリープ

### timeoutコマンド
[timeoutコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/timeout_1)を使用することでスリープ処理がおこなえます。

5秒待機する場合は以下のように記載します。

```
timeout /t 5 /nobreak > nul
```

なお、[timeoutコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/timeout_1)を以下のように記載することでpauseコマンドかわりにしようできます。

```
>timeout /t -1

続行するには何かキーを押してください ...

```

### pingコマンド
[pingコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/ping)のタイムアウトを使用する方法もよくつかわれます。
timeoutと違いミリ秒で指定できます。

5秒待機する場合は以下のように存在しないホストに対してPingを実行します。

```
ping 111.111.111.111 -n 1 -w 5000 > nul
```

### powershellでスリープ
PowerShellが入っている環境ではPowerShellの[Start-Sleep](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/start-sleep?view=powershell-6)コマンドを使用するといいでしょう。

5秒待機する場合は以下のように記載します。

```
powershell -command "Start-Sleep 5.0"
powershell -command "Start-Sleep -Milliseconds 5000"
```

## コンピュータの操作
### OSのバージョンを表示する
[verコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/ver)でオペレーションシステムのバージョンが取得できます。

```
>ver
Microsoft Windows [Version 10.0.17134.1006]
```

### ホスト名を表示する
[hostコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/hostname)でホスト名を表示します。

```
>hostname
NOTE-MAIN
```

### ネットワーク構成の情報を表示
[ipconfigコマンド]を使用することで現在のすべてのTCP / IPネットワーク構成値を表示できます。

```
>ipconfig

Windows IP 構成


イーサネット アダプター VirtualBox Host-Only Network:

   接続固有の DNS サフィックス . . . . .:
   リンクローカル IPv6 アドレス. . . . .: fe80REMdd98:fe1c:2a3c:ff4d%21
   IPv4 アドレス . . . . . . . . . . . .: 192.168.56.1
   サブネット マスク . . . . . . . . . .: 255.255.255.0
   デフォルト ゲートウェイ . . . . . . .:
```

### システム情報
[systeminfoコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/systeminfo)を使用することでローカルコンピュータまたはリモートコンピュータのシステム情報を表示します。

```
REM ローカルコンピュータのシステム情報
>systeminfo

REM リモートコンピュータのシステム情報を表示する
>systeminfo /S IEWin7 /U IEUser /P Passw0rd!
ホスト名:               IEWIN7
OS 名:                  Microsoft Windows 7 Enterprise
OS バージョン:          6.1.7601 Service Pack 1 ビルド 7601
OS 製造元:              Microsoft Corporation
OS 構成:                スタンドアロン ワークステーション
OS ビルドの種類:        Multiprocessor Free
登録されている所有者:
登録されている組織:     Microsoft
プロダクト ID:          00392-972-8000024-85432
最初のインストール日付: 2018/03/06, 19:59:43
システム起動時間:       2019/10/01, 16:02:36
システム製造元:         VMware, Inc.
システム モデル:        VMware Virtual Platform
システムの種類:         x64-based PC
プロセッサ:             1 プロセッサインストール済みです。
                        [01]: Intel64 Family 6 Model 142 Stepping 9 GenuineIntel ~2712 Mhz
BIOS バージョン:        Phoenix Technologies LTD 6.00, 2019/07/29
Windows ディレクトリ:   C:\Windows
システム ディレクトリ:  C:\Windows\system32
起動デバイス:           \Device\HarddiskVolume1
システム ロケール:      ja;日本語
入力ロケール:           en-us;英語 (米国)
タイム ゾーン:          (UTC-08:00) 太平洋標準時 (米国およびカナダ)
物理メモリの合計:       2,047 MB
使用できる物理メモリ:   1,609 MB
仮想メモリ: 最大サイズ: 4,095 MB
仮想メモリ: 使用可能:   3,659 MB
仮想メモリ: 使用中:     436 MB
ページ ファイルの場所:  C:\pagefile.sys
ドメイン:               WORKGROUP
ログオン サーバー:      N/A
ホットフィックス:       219 ホットフィックスがインストールされています。
                        [01]: KB2849697
                        [02]: KB2849696
~~~~~~略~~~~~~~~~~
                        [218]: KB982018
                        [219]: KB4516065
ネットワーク カード:    1 NIC(s) インストール済みです。
                        [01]: Intel(R) PRO/1000 MT Network Connection
                              接続名:           Local Area Connection 2
                              DHCP が有効:      はい
                              DHCP サーバー:    192.168.80.254
                              IP アドレス
                              [01]: 192.168.80.128
                              [02]: fe80REM151b:4382:b14b:d9e8
Hyper-V の要件:         VM モニター モード拡張機能: いいえ
                        ファームウェアで仮想化が有効になっています: いいえ
                        第 2 レベルのアドレス変換: いいえ
                        データ実行防止が使用できます: はい

```

### タスクの一覧を表示する
[tasklistコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/tasklist)を使用することでタスクの一覧を表示できます。

```
REM ローカルコンピュータのタスク一覧を表示
>tasklist

REM リモートコンピュータのタスク一覧を表示
>tasklist /S IEWin7 /U IEUser /P Passw0rd!

イメージ名                     PID セッション名     セッション# メモリ使用量
========================= ======== ================ =========== ============
System Idle Process              0                            0         24 K
System                           4                            0        960 K
smss.exe                       256                            0      1,024 K
csrss.exe                      324                            0      4,844 K
略
```

/fiオプションを使用することでフィルタを使用できます。
たとえばイメージ名がchrome.exeと一致するタスクの一覧を取得するには以下のようになります。

```
>tasklist /fi "IMAGENAME eq chrome.exe"
```

|フィルタ名|有効なオペレータ|有効な値|
|:---------|:---------------|:-------|
|STATUS|eq, ne|RUNNING|
|IMAGENAME|eq, ne|イメージ名|
|PID|eq, ne, gt, lt, ge, le|PID value|
|SESSION|eq, ne, gt, lt, ge, le|Session number|
|SESSIONNAME|eq, ne|Session名|
|CPUTIME|eq, ne, gt, lt, ge, le|CPUタイムを「HH:MM:SS」形式で指定します。MMとSSは0 ～ 59、 HH は正の数値です|
|MEMUSAGE|eq, ne, gt, lt, ge, le|メモリの使用量（KB）|
|USERNAME|eq, ne|Any valid user name|
|SERVICES|eq, ne|Service name|
|WINDOWTITLE|eq, ne|Windowタイトル|
|MODULES|eq, ne|DLL名を指定してDLLを使用しているタスクの一覧を取得します|

### タスクを終了する
[taskkillコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/taskkill)を使用してプロセスIDまたはイメージ名を指定してタスクを終了できます。

```
REM プロセスIDを指定して終了する
>taskkill /pid 26220 /pid 30392
成功: PID 26220 のプロセスに強制終了のシグナルを送信しました。
成功: PID 30392 のプロセスに強制終了のシグナルを送信しました。

REM イメージ名を指定して終了する
>taskkill /im notepad.exe
成功: プロセス "notepad.exe" (PID 30396) に強制終了のシグナルを送信しました。
成功: プロセス "notepad.exe" (PID 36840) に強制終了のシグナルを送信しました。

REM イメージ名にワイルドカードを指定して終了する
>taskkill ./im note*
成功: プロセス "notepad2.exe" (PID 31492) に強制終了のシグナルを送信しました。
成功: プロセス "notepad.exe" (PID 1140) に強制終了のシグナルを送信しました。

REM リモートコンピュータのタスクを終了する
>taskkill /s IEWin7 /u IEUser /p Passw0rd! /im notepad.exe
成功: プロセス "notepad.exe" (PID 996) は強制終了されました。

```

また[tasklistコマンドと同様に/fiオプションを使用してフィルタをかけて一括でタスクを終了できます。](#タスクの一覧を表示する)

```
>taskkill /fi "IMAGENAME eq notepad.exe"
```

### シャットダウン、再起動、ログオフ
[shutdownコマンド](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/shutdown)でシャットダウン、再起動、ログオフが可能です。

```
REM ログオフをする
shutdown /l

REM ただちに再起動をする
shutdown /r /t 0

REM ただちにシャットダウンする
shutdown /s /t 0
```


# まとめ
以上、簡単にコマンドプロンプトの操作やバッチファイルの使用例を公式ドキュメントベースでまとめました。

意外と大きな会社がやっているサイトのホームページでも、コマンドプロンプトやバッチファイルの使い方についての記事で参考文献に公式ドキュメントのリンクはっていない場合があるので、レビュアーが公式ドキュメント厨のときには攻略に役に立つと思います。

また、現在はPowerShellを使った方が楽だと思いますが、コマンドプロンプトでの操作やバッチファイルは自動化の基本となるものなので、軽く覚えておいた方が便利だと思います。

## おまけ：「PowerShellが実行できないよ！」
どういう状況かをいっているか認識があっているかわかりませんが、初期状態でスクリプトが実行ポリシーの問題で実行できないといっていると仮定します。

http://totech.hateblo.jp/entry/2017/09/29/162411

上記にあるようにやり方としては管理者権限をもって実行ポリシーを変更するか、以下のようなコマンドでスクリプトを実行します。これには管理者権限は不要です。

```
powershell -ExecutionPolicy RemoteSigned .\test.ps1
```