移転しました。

Windowsバッチのかゆいところメモ

Windowsバッチを久しぶりに書いたら、小学校の同級生の名前くらい思い出せなかったので、かゆいところをメモ。

実行コマンドを出力しない

デフォルトでシェルの-x付けたときと同じような状態なので、抑制するときには次のようにする。

@ECHO OFF

変数の代入

SETを使う。次の例では「B」と表示される。%date%とかみたいな標準で使える環境変数も上書きできるので注意。

SET A=B
ECHO %A%

変数の参照は「%変数名%」とする。あと、こんな感じで最後にセミコロンとかはつけないし、文字列をダブルクォートで括ったりしない。

エスケープシーケンス

エスケープシーケンスは「%」。「%」を表示したい場合などでは「%%」とする。次の例では「%」と表示される。

ECHO %%

コメントアウト

REMを使う、もしくは「::」を使う。次の例はコメントアウトなので何も実行されない。

REM SET A=B
:: ECHO %A%

引数を受け取る

実行時の引数は「%1」〜「%9」で受け取れる。「hoge.bat a b」と次のバッチを呼び出すと「ab」と出力される。

ECHO %1%2

複数行にわける

プログラムが横長になりすぎて途中で改行したい場合は最後に「^」をつける。次の例だと「abc」と出力される。

@ECHO OFF
ECHO a^
b^
c

条件分岐

IFを使う。否定は!=とか使わずにIF NOTを使う。次の例だと、第一引数がなければ上のIF、あれば下のIFブロックの中が実行される。この例の場合では()で括る必要はないけれども、複数コマンドを実行する場合には必ず()で囲む。

IF "%1" == "" (
    ECHO BLANK
)

IF NOT "%1" == "" (
    ECHO NOT BLANK
)

理由はよくわからないけど、IFで引数調べるときにはダブルクォートで括らないと構文エラーになる。
IF-ELSEやIF-ELSE IFは普通に書ける。

IF "%1" == "" (
    ECHO BLANK
) ELSE (
    ECHO NOT BLANK
)

IF "%1" == "" (
    ECHO BLANK
) ELSE IF NOT "%1" == "" (
    ECHO NOT BLANK
)

繰り返し

FORを使う。次の例では「a b c」と改行区切りに出力される。%%Iにループ中の現在値が代入される。名前は「I」である必要はない。

FOR %%I IN (a b c) DO (
    ECHO %%I
)

実行する行を移動する

いわゆるGOTO文。ラベルに移動できる。次の例では第一引数がない場合にENDラベルにジャンプする。

IF "%1" == "" GOTO :END

ECHO SKIP THIS LINE

:END

ファイルがあるかどうか調べる

IF EXISTを使う。否定の場合はIF NOT EXISTを使う。次の例ではhoge.txtが存在する場合には上のコードのECHOが実行されて、hoge.txtが存在しない場合には下のコードのECHOが実行される。

IF EXIST hoge.txt (
    ECHO hoge.txt is exists
)

IF NOT EXIST hoge.txt (
    ECHO hoge.txt is not exists
)

ファイルを読み込む

ファイルの内容を一行ずつ読み込む場合などでは、FORの/Fオプションを使う。次の例ではhoge.txtの内容を一行ずつ出力する。

FOR /F %%I IN (hoge.txt) DO (
    ECHO %%I
)

ファイルの内容を調べる

いわゆるgrep。FINDSTRを使う。正規表現も使える。詳しくはHELP FINDSTRとかで確認するとして、次の例ではhoge.txtに「abc」があれば、マッチした行が出力される。

FINDSTR "abc" hoge.txt

ファイルの内容で条件分岐する

FINDSTRを使って内容によって条件分岐したい場合はERRORLEVELを条件にする。ただし、IFやFORブロックの中だと常にERRORLEVELが0になってしまうので、このやり方では正しく分岐できなかった。

FINDSTR "abc" hoge.txt
IF NOT ERRORLEVEL 1 (
    ECHO contain abc
)

標準出力を抑制する

標準出力に出力されてしまうのを抑制するには「> NUL」で出力をNULに渡す。/dev/nullに渡すのと同じ感じ。次の例では、FINDSTRにマッチした文字列を出力しない。

FINDSTR "abc" hoge.txt > NUL

本日の年月日

%date%の値(YYYY/MM/DD)を分解する。参考: バッチ・ファイル中で日付をファイル名に使用する − @IT

ECHO %date:~-10,4%%date:~-5,2%%date:~-2,2%

昨日の年月日

取得する手段がないみたい。閏年を含む計算を自前でやる方法は見つかったけど。潔くVBScriptなど使う。環境さえ許せばPerlなどを使いましょう。

コマンドプロンプトから外部VBScriptを起動する

CSCRIPTを使う。次の例ではhoge.vbsが起動する

CSCRIPT hoge.vbs