コンピュータ系の仕事をしているとWindowsバッチ(.bat or .cmd)を書くことがままあります。
よく見かけるのは構造化もされていないベタ書きのものが多いです。
その場限りの処理を書く場合はベタ書きで良いのですが、ある程度まとまった処理を書く場合は関数化しておくほうが今後の使いまわしを考えると効率的です。
ここでは何回かに分けてWindowsバッチ(今後は単にバッチと記載します)を関数化する場合の方法と注意点について説明します。
callを使う方法
バッチではcallを使ってバッチ内に記載された関数(サブルーチン)を呼び出す事が出来ます。
下記で単純にcallを使用した場合の書き方について説明します。
単純にcallを使用した例と問題点
バッチで関数を定義するには「:関数名」~「goto :eof」の間に実行したい処理を書きます。
下記例では「display_date_time」と言う関数を定義しています。
batch_function01.cmd
@echo off
rem ########################################################
rem # 現在日時表示関数
rem ########################################################
:display_date_time
echo 現在の日時は%date% %time%です。
goto :eof
rem ########################################################
rem # メイン処理
rem ########################################################
echo 処理開始
call :display_date_time
echo 処理終了
ただこのバッチを実行しても残念ながら期待通りには動きません。
期待する動き
>batch_function01.cmd
処理開始
現在の日時は2021/04/11 9:34:24.49です。
処理終了
実際の動き
>batch_function01.cmd
現在の日時は2021/04/11 9:34:24.49です。
これは「:display_date_time」の書き方が本来は関数の定義ではなく「call」や「goto」で処理を飛ばす先を指定するのに使われるものだからです。
上から処理が実行されていき「:display_date_time」を通って、日時表示後に「goto :eof」で処理が終了してしまうためこのような表示になります。
改良版callを使用した例
上記問題に対応するために「call :main」の後に「goto :eof」を追加します。
batch_function02.cmd
@echo off
rem ########################################################
rem # メイン関数実行
rem ########################################################
call :main
goto :eof
rem ########################################################
rem # 現在日時表示関数
rem ########################################################
:display_date_time
echo 現在の日時は%date% %time%です。
goto :eof
rem ########################################################
rem # メイン関数定義
rem ########################################################
:main
echo 処理開始
call :display_date_time
echo 処理終了
goto :eof
このバッチを実行すると以下の結果になります。
改良版の実行結果
>batch_function02.cmd
処理開始
現在の日時は2021/04/13 21:45:36.40です。
処理終了
これで期待する動きになりましたね。
新たな問題
さてこれで無事にバッチで関数が実現できたように見えますが、実はまだ問題があります。
今回紹介したバッチは変数を使用していないので問題にならないのですが、変数を使用する場合に問題が出てきます。
これはここで紹介したバッチの書き方をした場合、変数のスコープが一つしかなくすべてがグローバル変数のようになってしまうためです。
次回の記事では具体的にどのような問題が出るのかとそれをどう解決すればよいか紹介します。
サンプルバッチ
ここで紹介したバッチを実行してみたい方はGitHubにバッチをアップロードしているので気になる方はチェックしてみて下さい。