今回はBATの”おまじない”的なSETLOCAL・ENDLOCALの使用方法についてご紹介します。
SETLOCAL・ENDLOCALとは?
BAT内だけで使用するローカル環境変数を扱うもので、主に
- コマンドプロンプトを開いた状態で、複数のBATファイルを実行する場合
- メインBATからサブBATを呼びだす場合
に使われます。
・SETLOCALとは
BAT内で使用するローカル環境変数を作成します。
ローカル環境変数はENDLOCAL又はBATの終わりに達したとき終了します。
・ENDLOCALとは
ローカル環境変数を終了します。
それでは次項から具体例で説明します。
SETLOCAL・ENDLOCALを使わないと起こる不具合
不具合の例として、メインバッチとサブバッチの環境変数名が同じで、サブバッチ内でも値をセットしてしまったものを紹介します。
メインバッチ
@ECHO OFF
SET TMP1=TEST END
@REM 処理実行
CALL TEST.BAT
ECHO %TMP1%
サブバッチ
SET TMP1=C:\Windows
REM ~~~処理~~~
処理結果
C:\Windows
このように同じ環境変数を使用してしまったせいで、本来であれば、処理終了を示す「TEST END」と表示するはずでしたが、サブバッチでセットした「C:\Windows」が表示されてしまいました。
今回の例であればサブバッチを1つしか呼び出しておらず、セットした内容も全く異なるため、簡単にバグだと発見できました。ただこれが複数のサブバッチでセットする内容も似たような値であれば、原因分析が困難な上に、処理結果を見ても間違いに気づかない可能性があります。
もちろん、サブバッチでセットした値をサブバッチ終了時に解放しても同じです。
サブバッチ
SET TMP1=C:\Windows
REM ~~~処理~~~
SET TMP1=
処理結果
ECHO は <OFF> です。
このように、サブバッチ内で解放してもNULLがメインバッチの環境変数に反映されてしまいました。
開放もできないとなると、メインバッチとサブバッチで環境変数名が被らないように注意するしかない?と思うかもしれませんが、そこで使用するのがSETLOCAL・ENDLOCALになります。
SETLOCAL・ENDLOCALを使った場合
先ほどの例にSETLOCAL・ENDLOCALを使いました。メインバッチは先ほどと同じです。
サブバッチ
SETLOCAL
SET TMP1=C:\WINDOWS
REM ~~~処理~~~
ENDLOCAL
処理結果
TEST END
この通り、期待していた処理結果となりました!
SETLOCAL ENDLOCALは先頭・末尾でないといけない?
結論から申し上げますと、SETLOCAL・ENDLOCALの位置はどこでも構いません。ローカル環境変数を始めたい箇所にSETLOCALを設定し、終わりたい箇所でENDLOCALを設定すれば問題ありません。
なので、以下のような使い方ができます。
メインバッチ
@ECHO OFF
SET TMP1=~~~処理~~~
@REM 処理実行
CALL TEST.BAT
サブバッチ
ECHO %TMP1%
SETLOCAL
SET TMP1=!!処理中!!
ECHO %TMP1%
REM ~~~処理~~~
ENDLOCAL
ECHO %TMP1%
処理結果
~~~処理~~~
!!処理中!!
~~~処理~~~
このように、
SETLOCALまではメインバッチの環境変数
SETLOCALからはサブバッチのローカル環境変数
ENDLOCAL後はメインバッチの環境変数
が使われます。
ただ、バッチ間で環境変数を共有すること自体がバグに繋がる可能性がありますので、当サイトではSETLOCAL ENDLOCALは先頭・末尾であることを推奨します。