バッチ作成の手引き

#プロローグ
アウトプットすると勉強になるので、自分用にバッチ作成の手引きを作成する。
気づきがあれば順次追記していく。

#バッチとは
>
バッチファイル（英: batch file）とは、MS-DOS、OS/2、Windowsでのコマンドプロンプト（シェル）に実行させたい命令列をテキストファイルに記述したもの。バッチファイルを実行すると、シェルプログラム（一般にCOMMAND.COMやcmd.exe）がそのファイルを読み、その中のコマンドを（通常）一行ずつ実行する。バッチファイルはUNIX系オペレーティングシステムのシェルスクリプトに相当する。

#基本

##ファイル名
hogehoge.bat
hogehoge.cmd

##実行方法
###実行する
1.ダブルクリックする
2.コマンドプロンプトから指定してEnterする
###引数を渡して実行する
test.bat aaa.txt

##出力
###出力する
```
>echo hogehoge
hogehoge
```

##変数
###定義する
```bat
set hoge1=abc
```
###利用する
1つ目が通常の変数
2つ目の感嘆符を利用するのは後述の遅延環境変数で説明
3つ目は引数参照パターン

```bat
echo %hoge1%
echo !hoge1!
echo %数字
```

引数参照パターン

```bat:test.bat
@echo off

echo %1
echo %2
echo %3
```


```
C:\work\bat_practice>test.bat aaa bbb
aaa
bbb
ECHO は <OFF> です。
```

##関数
###定義する
コロンを先頭に付与する

```bat
:test
echo test1
```

###呼び出す
callは関数呼び出しのイメージ、gotoは単語のごとく移動するイメージ

```bat
call :test
goto test
```

##コメントアウト
通常の使い方

```bat
REM コメントアウト
```

ラベルを使った変則的な使い方
通常は関数として処理を分けるのに利用されるコロンを、定義していないもの指定することでコメントアウトとして利用できる。
また、このままでは通常のコロンの使い方と混同されるため、2行目のようにコロン２つで扱われることが多い。
しかし、こちらはこちらで可読性がありそうだが、ifやfor内などでコメントアウトとして動作しない場合があるため、注意が必要。

```bat
: コメントアウト
:: コメントアウト
```
コメントアウトとして動作しないパターン(もちろんremだと動く)

```bat:test.bat
@echo off

if exist C:test.bat (
	:: Comment line 1
	echo test
	:: Comment line 2
)
```

```
C:\work\bat_practice>test.bat
) の使い方が誤っています。
```

##ループ
バッチの繰り返し構文はfor一択
繰り返し対象をオプション指定して選択する

###数指定の繰り返し
pの部分は任意のアルファベット、カッコの中で(開始,増加数,終値)を指定している

```bat
for /l %%p in (0,1,5) do (
 echo helloworld!!
)
```

```
C:\work\bat_practice>test.bat
0
1
2
3
4
5
```

###ファイル群の繰り返し
カッコで指定した条件に適応するファイルを順番に処理する

```bat
for %%p in (*.log) do (
 echo %%p
)
```

###ファイル内容の繰り返し
カッコで指定したファイルの内容について処理する
tokensで対象カラムを指定する。1,2なら1列と2列が対象、1-5なら1列から5列が対象、すべては*で指定できる
delimsは区切り文字を指定する。区切り文字がスペースなら指定不要。
%%aとしておけば、2列目はb、10列目はjとアルファベットのインクリメントで指定できる。

```bat
for /f "tokens=1-10 delims=," %%a in (hoge.csv) do (
  echo %%b %%j
)
```

```
C:\work>type hoge.csv
1,2,3,4,5,6,7,8,9,10,11
C:\work>test.bat
2 10
```
##条件式
if一択。
条件は==,equ,neq,gtr,geq,leq,lss,exist,errorlevelなどが利用できる

```bat
set hoge=test

if not %hoge% == test (
    echo yes
) else (
    echo no
)
```

```
C:\work>test.bat
no
```

##終了コード
バッチの異常系処理に必須となるerrorlevel
正常なら0、異常なら1、他にも10とかある

```bat
dir /b
echo %errorlevel%
dir \\naiyo\
echo %errorlevel%
```

###


```
C:\work>test.bat
test.bat
0
指定されたパスは無効です。
1
```


#とりあえず覚えとけ
###@echo off
バッチの先頭に記述する。「＠」でコマンドを非表示にできる。「echo off」で全行を非表示にできる。
よって@echo offですべてのコマンド記述を非表示にする

```bat
@echo off
```

###setlocal enabledelayedexpantion
遅延環境変数を利用する際に冒頭で宣言しておく
こいつがバッチの鬼門
バッチの変数はforやifなどに入った時に確定する。
よって、if内部で呼び出した%hoge%はif呼び出しの前に確定した0が出力される
また、if内部で呼び出した!hoge!は遅延環境変数を利用しているので、echo !hoge!された瞬間に確定するので、1が出力できる

```bat
@echo off

setlocal enabledelayedexpansion

set hoge=0

if %hoge% == 0 (
  set /a hoge += 1
  echo %hoge%
  echo !hoge!
)
```

```
C:\work\bat_practice>test.bat
0
1
```

###exit /b
/bのヘルプ。よって、最初に起動されたコマンドプロンプトの画面が終了しないようにできる。
>CMD.EXE ではなく、現在のバッチ スクリプトを終了するように指定します。
バッチ スクリプトの外から実行された場合、CMD.EXE を終了させます。

###文字列置換

%変数:変更前文字列=変更後文字列%

```bat
set hoge=test
echo %hoge:st=st12345%
pause
```

```
C:\work\bat_practice>echo test12345
test12345
```

###文字列抽出
```bat
set hoge=test
echo %hoge:~0,2%
```

```
C:\work>set hoge=test
C:\work>echo te
te
```

###リダイレクト
linuxと同じ。エラーと標準を出力

```bat
echo %hoge% >> test.log 2>&1
```


#よく使うパターン集
###cd /d %~dp0
バッチ格納パスをカレントパスにする
%数字で前述のとおり引数を示すが、0はバッチ自体を示す。~dpは単なる利用オプション

###set batFileName="%~nx0"
自身のバッチファイル名を取得する
考え方は上に同じ

###copy nul > hoge.txt
nulをコピー元にして空ファイルを作成する

###timeout /t 1 /nobreak
スリープ。
Windows7以前は、pingが1秒かかることを利用してこんな方法で使われていた。

```bat
ping /n 1 localhost >nul
```

###日時
dateとtimeの予約変数を利用した文字列抽出の応用

```bat
set yyyy=%date:~0,4%
set mm=%date:~5,2%
set dd=%date:~8,2%
set hh=%time:~0,2%
set mi=%time:~3,2%
set ss=%time:~6,2%
echo %yyyy%%mm%%dd%%hh%%mi%%ss%
```