バッチの個人的まとめ 

# 目的
たまにバッチを作ることがあり、毎回調べている。。
よく使う内容を個人的にまとめておく。
目指す内容に近い記事があったので、そちらを見た方がいいかも。(以下の参考文献のref5)

# 参考文献
[(ref1) とほほのバッチ入門 / とほほのWWW入門](https://www.tohoho-web.com/ex/bat.html)
[(ref2) バッチファイルでコメントを使用する / 知識ゼロからのwindowsバッチファイル超入門](https://jj-blues.com/cms/wantto-usecommentout/)
[(ref3) 「%~dp0」を理解すれば、Windowsバッチ中でディレクトリ名やファイル名を自由に使えるから便利 / ぱーくん plus idea](https://plus-idea.net/know-dp0-windows-meaning/)
[(ref4) errorlevelの値から分岐処理を行う / 知識ゼロからのwindowsバッチファイル超入門](https://jj-blues.com/cms/wantto-errorlevelbranch/)
[(ref5) Windowsバッチまとめ / Qiita](https://qiita.com/tomotagwork/items/5b9e08f28d5925d96b5f)
[(ref6) バッチファイルでコメントを書く方法 / そまちょブログ](https://somachob.com/bat-comment/)
[(ref7) バッチファイルのエスケープ文字は^だ！！ / みちしるべ](https://orangeclover.hatenablog.com/entry/20100811/1281537172)
[(ref8) BATファイルで文字列の切り出し / アプ研](https://www.upken.jp/kb/kZwpzAqblKfZDjtMXuWuwioeExKNdE.html)

# まずは超簡単な例を説明
```
@echo off

rem aaaと出力するだけの実用性のないバッチです。出力結果を確認できるようにpauseで処理を止めています。
echo aaa
pause

exit /b 0
```

:::note info
Windowsのコマンドの意味を調べるには/?を使うとよい。
(例) echo /?
:::

## rem
コメントアウト
コメントアウトはremの他にも、コロン(:), コロン2つ(::)でも代用可能。(稀にしか見ないが)
rem/ || (...)で複数行にわたってコメントアウト可能らしい。(詳細はref6参照)

## echo
>ECHO [ON | OFF]
>ECHO [メッセージ]
  
@echo offを設定しておくと、以降のメッセージ出力をしないようにする。
echoでメッセージの出力が可能。
echo.で改行のみの出力が可能。

## pause
バッチプログラムの処理を一時停止することが可能。デバッグ用に使うことが多いと思う。

## exit
>EXIT [/B] [終了コード]

exitは基本的には/bのオプションを設定した方がいいと思う。
⇒バッチだけが終了してバッチを起動したコマンドプロンプトが残る。
バッチの戻り値を設定することができ、%ERRORLEVEL% で参照することができます。

# 基本的な説明
## 引数
バッチファイルへの引数は %1, %2, %3, ..., %9 で参照できます。%0 はコマンド名を示します。
また、以下のようにオプションがいくつかあります。
|  | 意味 |
|:--|:--|
| ~ | ドライブ、ファイルパスから「”」を取り除きます。 |
| d | ドライブの情報を取り出す |
| p | パス名の情報を取り出す |
| n | ファイル名の情報を取り出す |
| x | ファイル拡張子の情報を取り出す |

(実用例)
```
C:\temp> sample.bat aaa "bbb"
```
|  | 意味 | 例 |
|:--|:--|:--|
| %0 | コマンド名 | C:\temp\sample.bat |
| %~dp0 | %0をドライブ文字とパスだけに展開 | C:\temp |
| %~nx0 | %0をファイル名と拡張子だけに展開 | sample.bat |
| %1 | 第一引数 | aaa |
| %2 | 第二引数 | "bbb" |
| %~2 | 第二引数("を除去) | bbb |

## set
set は環境変数に値を設定します。
環境変数を表示するには、環境変数名を %...% で囲みます。
後述の遅延展開している時は、環境変数名を!...!で囲うことで値の変更を反映できる(遅延展開時に評価してくれる)。

## if文
ここは参考文献(ref1)によくまとまっているので転記。
>if Condition Command
if Condition ( Commands... )
if Condition ( Commands... ) else ( Commands... )
if Condition ( Commands... ) [else if Condition ( Commands... )]... else ( Commands... )
Condition ::=
  [not] [/i] Value1==Value2
  [not] exist FileName
  [not] defined VariableName
  [/i] Value1 Ope Value2
Ope ::=
  equ | neq | gtr | geq | lss | leq

文字列同士の比較には==を使う。
数値同士の比較にはequ等の比較演算子を使う。
括弧と改行の位置が悪いとエラーになるので、サンプルを載せておく。
```
@echo off
set param1=aaa
set num1=1

if %param1%==aaa (
  echo param1 is aaa
)

if %num1% equ 2 (
  echo num1 is 1
) else (
  echo num1 is not 1
)
pause
exit /b 0
```

## for文
ここも参考文献(ref1)によくまとまっているので転記。
>for %%v in (files) do ( Commands )
for /R %%v in (files) do ( Commands )
for /D %%v in (directories) do ( Commands )
for /L %%v in (start, increment, end) do ( Commands )
for /F ["FOptions"] %%v in (file) do ( Commands )
for /F ["FOptions"] %%v in ('Command') do ( Commands )
FOptions ::=
  delims=string
  tokens=n, ...
  skip=n
  eol=string
  usebackq

ファイル群に対してループ処理を行う。
>for %%f in (C:\temp\*.txt) do echo %%f

/rを指定すると、サブフォルダを含めて再帰的に検索する。
>cd C:\temp
for /r %%f in (*.txt) do echo %%f

/dを指定すると、ファイルではなくディレクトリを対象に処理を行う。
>cd C:\temp
for /d %%d in (*) do echo %%d

コマンドを実行する。(同様にバッチやpowershellも呼び出し可能)
なお、バッチファイルのエスケープ文字は^となっている。
>for /f "usebackq" %%i in (\`set ^| findstr USER \`) do echo %%i
>for /f "usebackq tokens=2 delims=," %%i in (\`C:\temp\aaa.bat\`) do echo %%i
>for /f "usebackq" %%i in (\`powershell -ExecutionPolicy bypass -File C:\temp\bbb.ps1\`) do echo %%i



## 遅延展開
%name%の形式だと、for文を評価する時点で変数が展開されてしまう。
それを解決するにはループをsetlocal enabledelayedexpansion ... endlocalで囲み、変数参照時の%を!に変更する
```
@echo off
setlocal enabledelayedexpansion
for /L %%n in (1, 1, 3) do (
    set name=Yamada%%n
    echo My name is !name!
)
endlocal
pause
exit /b 0
```
## ラベルとgoto
コロン(:)でラベルを定義できる。また、gotoでラベルに移動できる。
>echo aaa
>goto OnError
>echo This line cannot be reached
>
>:OnError
>echo Error happened

## callとサブルーチン
callでコマンドを実行したり、他のバッチを(同じウィンドウで)呼び出すことができる。
>call notepad.exe
>call C:\temp\aaa.bat

また、サブルーチンを呼び出すことができる。
>call :echoMessage "some message"
>
>:echoMessage
>echo %~1

## start
startでコマンドを実行したり、他のバッチを(別のウィンドウで)呼び出すことができる。(callの方が便利？)
>start notepad.exe
>start C:\temp\aaa.bat

/bのオプションを指定すると、同じウィンドウ内でバッチを呼び出せる。
> start /b C:\temp\aaa.bat

## errorlevel
参考文献(ref4)から転記。errorlevelの値(サブルーチン等の実行結果)に応じて処理分岐が可能。
>if errorlevel [数値] [[数値]以上の場合の処理]
>if not errorlevel [数値] [[数値]未満の場合の処理]

コードのサンプル
```
@echo off
 
rem 「errorlevel」を設定するサブルーチンの呼び出し
call :set_errorlevel
 
rem 777以上の場合
if errorlevel 777 echo 終了コードは777以上です。
rem 777未満の場合
if not errorlevel 777 echo 終了コードは777未満です。
  
rem 「errorlevel」を設定するサブルーチン
:set_errorlevel
exit /b 777
```

## 文字列操作
ここは参考文献(ref8)によくまとまっているので転記。
| 書式 | 意味 |
|:--|:--|
| %V% | 変数Vの値全体 |
| %V:~m% | m文字目から、最後まで |
| %V:~m,n% | m文字目から、n文字分 |
| %V:~m,-n% | m文字目から、最後のn文字分を除いたもの |
| %V:~-m% | 後ろからm文字目から、最後まで |
| %V:~-m,n% | 後ろからm文字目から、n文字分 |
| %V:~-m,-n% | 後ろからm文字目から、最後のn文字分を除いたもの |
| %V:c1=c2% | 文字c1を文字c2に置換する。それぞれ複数の文字を指定することも可能 |