バッチ作成の手引き


プロローグ

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

バッチとは

バッチファイル(英: 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

変数

定義する

set hoge1=abc

利用する

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

echo %hoge1%
echo !hoge1!
echo %数字

引数参照パターン

test.bat
@echo off

echo %1
echo %2
echo %3
C:\work\bat_practice>test.bat aaa bbb
aaa
bbb
ECHO は <OFF> です。

関数

定義する

コロンを先頭に付与する

:test
echo test1

呼び出す

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

call :test
goto test

コメントアウト

通常の使い方

REM コメントアウト

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

: コメントアウト
:: コメントアウト

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

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の部分は任意のアルファベット、カッコの中で(開始,増加数,終値)を指定している

for /l %%p in (0,1,5) do (
 echo helloworld!!
)
C:\work\bat_practice>test.bat
0
1
2
3
4
5

ファイル群の繰り返し

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

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

ファイル内容の繰り返し

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

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などが利用できる

set hoge=test

if not %hoge% == test (
    echo yes
) else (
    echo no
)
C:\work>test.bat
no

終了コード

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

dir /b
echo %errorlevel%
dir \\naiyo\
echo %errorlevel%
C:\work>test.bat
test.bat
0
指定されたパスは無効です。
1

とりあえず覚えとけ

@echo off

バッチの先頭に記述する。「@」でコマンドを非表示にできる。「echo off」で全行を非表示にできる。
よって@echo offですべてのコマンド記述を非表示にする

@echo off

setlocal enabledelayedexpantion

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

@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 を終了させます。

文字列置換

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

set hoge=test
echo %hoge:st=st12345%
pause
C:\work\bat_practice>echo test12345
test12345

文字列抽出

set hoge=test
echo %hoge:~0,2%
C:\work>set hoge=test
C:\work>echo te
te

リダイレクト

linuxと同じ。エラーと標準を出力

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秒かかることを利用してこんな方法で使われていた。

ping /n 1 localhost >nul

日時

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

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%