今更ながらDOSバッチ
仕事上、コマンドプロンプトで実行される
バッチファイルを作成する機会が多いので、
備忘録がてらメモしてみる。
なお、当エントリーでは、コマンドをすべて
大文字で記載しているが、別に小文字でも
問題ないので、その辺はお気になさらず。
1.冒頭のおまじない
@ECHO OFF … 実行中のコマンド非表示
SETLOCAL … 環境変数の操作のローカル化
無論、SETLOCALと対を為すENDLOCALという
コマンドもあるが、バッチ終了時に暗黙的に
自動実行されるため、基本的に書かなくてもいい。
2.コメント
REM コメント … 正しいコメント方法
:コメント … ラベルをコメントとして使用
なお、複数行をコメントアウトしたい場合、
GOTO文とラベルを使って対象を「GOTO :○○」
「:○○」で囲えば無理矢理実現できる。
3.システム日付・時刻
日付の場合は一発でYYYYMMDD形式で取得できる。
%DATE:/=% … 「/」を除去した日付
なお、曜日を取得しようと思うと
それなりに作りこみが必要。
時刻の場合、一発でhhmmss形式で
取得することができない。そのため、
変数Tに欲しい形式で加工する。
SET T=%TIME:~0,8% … %TIME%の先頭8文字取得
SET T=%T::=% … 「:」を除去
SET T=%T: =0% … 半角スペースを0埋め
これでTにhhmmss形式でシステム時刻が
セットされる(ミリ秒は除外している)。
4.実行ファイル
コマンドプロンプトで「CALL /?」と叩けば
詳細を教えてくれる。
%0 … フルパスのファイル名(""あり)
%~0 … フルパスのファイル名(""なし)
%~f0 … フルパスのファイル名
%~d0 … ドライブ文字
%~p0 … ドライブ文字以降のパス
%~n0 … ファイル名
%~x0 … ファイル拡張子
%~s0 … フルパスのファイル名(短縮あり)
%~a0 … ファイルの属性
%~t0 … ファイルのタイムスタンプ
%~z0 … ファイルのサイズ
%~dp0 … ファイル格納先のフルパス
%~nx0 … 拡張子つきのファイル名
%~ftza0 … DIRコマンド風の出力
なお、
「C:\Users\Public\Desktop\CommandPrompt_TEST\echo.bat」
に上記内容を記述して出力した結果は
下記の通りである。
%0 "C:\Users\Public\Desktop\CommandPrompt_TEST\echo.bat"
%~0 C:\Users\Public\Desktop\CommandPrompt_TEST\echo.bat
%~f0 C:\Users\Public\Desktop\CommandPrompt_TEST\echo.bat
%~d0 C:%~p0 \Users\Public\Desktop\CommandPrompt_TEST\
%~n0 echo
%~x0 .bat
%~s0 C:\Users\Public\Desktop\COMMAN~1\echo.bat
%~a0 --a--------
%~t0 2017/11/24 20:40
%~z0 189
%~dp0 C:\Users\Public\Desktop\CommandPrompt_TEST\
%~nx0 echo.bat
%~ftza0 --a-------- 2017/11/24 20:40 189 C:\Users\Public\Desktop\CommandPrompt_TEST\echo.bat
5.引数
変数%0が自分自身を表す変数であったのに対し、
%1、%2、%3、…というのは、バッチ実行時に
渡された引数の内容を表す変数である。
test.bat "hoge.txt" 1
としてtest.bat実行時に引数が渡された場合、
ECHO %1 … "hoge.txt"
ECHO %2 … 1
が格納されることになる。
ちなみに、引数は%1~%9までの最大9個まで
しか渡すことができず、それ以上の引数を
渡したい場合は作りこみが必要。
7.DOS窓からの入力
SET /P 変数名="入力を促すメッセージ"
でDOS窓からの入力を受け取ることが出来る。
よくあるパターンとして、
SET /P I="処理を実行します。よろしいですか?(Y/N): "
IF "%I%"=="Y" (GOTO MAIN)
IF "%I%"=="y" (GOTO MAIN)
EXIT
:MAIN
(以降、メイン処理を記述)
のように、処理実行前の確認用として
用いられることが多い。
8.リダイレクト出力
> ファイル名 … 標準出力(新規)
>> ファイル名 … 標準出力(追記)
2> ファイル名 … 標準エラー出力(新規)
2>> ファイル名 … 標準エラー出力(追記)
> NUL 2>&1 … NULL破棄
(おまけ)
ECHO. … 空行の出力
最後の空行出力は、リダイレクトと直接関係は
ないような気がするけど、まぁよく使う
コマンドなので、とりあえずここに記載。
9.デバッグ確認
処理の中で不具合が検出された場合、
ECHO %変数名% … 変数のウォッチ
PAUSE … 処理の一時停止(ブレーク)
を駆使すれば、変数の中身の変遷を
追いかけることが出来る。
10.サブルーチン定義
バッチには関数が定義できない。そのため、
ラベルを用いてサブルーチンを定義する
手法がよく用いられる。以下、例を挙げる。
@ECHO OFF
SETLOCAL
CALL :SUB1 %~dp0
ECHO %ERRORLEVEL%
CALL :SUB2 "fuga.txt"
ECHO %ERRORLEVEL%
ECHO.
PAUSE
EXIT
:SUB1
IF "%~d1"=="C:" EXIT /B 0
IF "%~d1"=="D:" EXIT /B 1
:SUB2
IF EXIST %1 EXIT /B 0
IF NOT EXIST %1 EXIT /B 1
簡単に説明しておくと、まずSUB1をCALL
する際に引数%~dp0を渡している。
これは、バッチを実行しているファイルの
ドライブ文字で、SUB1でドライブ文字の
判定を行っている。ドライブが「C:」であれば
0を、「D:」であれば1をエラー用変数に返す。
その後、SUB2をCALLして引数"fuga.txt"を渡す。
SUB2では"fuga.txt"がバッチが格納されている
フォルダに存在するか判定しており、ファイルが
あれば0を、なければ1をエラー用変数に返す。
なお、実行結果はこうなった。
0 … ドライブは「C:」
1 … "fuga.txt"は存在しない
続行するには何かキーを押してください . . .
ラベルを用いた場合、メイン処理の末尾に
「EXIT」コマンドを入れておかないと、ラベルに
記述した処理がすべて実行されてしまう。
また、サブルーチンの終了時は「EXIT /B」に
しないとサブルーチンどころかバッチそのものが
終了してしまうため注意が必要である。
おわりに
さて、思ったより長くなってしまった。
IFやFORの構文も書こうと思ったけど力尽きた。
どうせHELPコマンド叩けばすぐに分かるし…
まぁ、気が向いた時に更新しようと思う。
しかし、Windowsのスクリプト言語と言えば
Powershellがもう少しメジャーに扱われても
いいような気がするが、現場レベルで言うと
やはりまだまだDOSバッチやVBscriptが幅を
利かせているのが現状ではなかろうか。
バッチ作成は普通にテキストエディタ使えば
問題なく作成できるが、VisualBatなる
IDEも存在するので、気になる方は
使用されてみては如何だろう。
では、これにて失礼。