コマンドプロンプト

今回は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は先頭・末尾であることを推奨します。

まとめ

・SETLOCAL・ENDLOCALを使えば、BAT内だけで使用するローカル環境変数を扱うことができる
・サブバッチの先頭・末尾に必ずSETLOCAL ENDLOCAL宣言したほうが好ましい

バッチ開発の際は必須に近いコマンドなので、是非使ってみてください。