S_a_k_Uの日記みたいなDB

~サクゥーと呼ばないで~

Windowsバッチのパラメータの修飾子により取得できる値

バックアップのバッチファイルを作ってて、ログファイル名を生成する時に遭遇した事象。
Windowsバッチのパラメータ%0を参照すれば、実行しているバッチファイル名を取得することができる。
ファイル名のみを取得する場合は、Windowsバッチのパラメータの修飾子により%~n0で取得することができる。
とした時に、Windowsバッチファイル内でサブルーチンを呼び出した場合、呼び出し先のサブルーチンで取得できる値に違いがあった。

動作の違いの例

Windowsバッチファイル名(フルパス):K:\TEST\TEST.bat
呼び出し先のサブルーチン名:subroutine

参照した値 起動したWindowsバッチファイルのメイン 呼び出し先のサブルーチン
%0 K:\TEST\TEST.bat subroutine
%~n0 TEST TEST

パラメータ%0の値が異なるのはそういう動作としたとしても、修飾子により参照した%~n0の値が同じになるのがイマイチ納得できない…

サンプルコード

サンプルコードでは、外部のバッチファイルを呼び出した時の動作も確認している。
起動元のバッチファイル:TEST.bat

echo off
ver
echo.
echo -------- 起動元のバッチファイル --------
echo [起動元のバッチファイルのメイン]
echo %0
echo %~n0
call :subroutine
call %~dp0TEST_SUB
pause
exit /b

:subroutine
echo [起動元のバッチファイルのサブルーチン]
echo %0
echo %~n0
exit /b

サブのバッチファイル:TEST_SUB.bat

echo off
echo -------- サブのバッチファイル --------
echo [サブのバッチファイルのメイン]
echo %0
echo %~n0
call :subroutine_SUB
pause
exit /b

:subroutine_SUB
echo [サブのバッチファイルのサブルーチン]
echo %0
echo %~n0
exit /b

サンプルコードの実行結果

>k:\test\test.bat

>echo off

Microsoft Windows [Version 10.0.17134.191]

-------- 起動元のバッチファイル --------
[起動元のバッチファイルのメイン]
k:\test\test.bat
TEST
[起動元のバッチファイルのサブルーチン]
:subroutine
TEST
-------- サブのバッチファイル --------
[サブのバッチファイルのメイン]
k:\TEST\TEST_SUB
TEST_SUB
[サブのバッチファイルのサブルーチン]
:subroutine_SUB
TEST_SUB
続行するには何かキーを押してください . . .

念のための確認

起動元のバッチファイルのメインで「%~n0」を参照することで、最初に参照した値で固定されてしまうのでは?と思い、起動元のバッチファイルのメインの「echo %~n0」をコメントアウトしてみたが、呼び出し先のサブルーチンで取得できる値の結果は同じであった。

その他気が付いたこと

バッチファイルの起動方法で、パラメータ%0を参照した時の値に2点違いがあった。
「パラメータ%0がダブルクオーテーションで囲まれるかどうか」と「パスの大文字小文字」

起動方法 囲まれる 大文字小文字
エクスプローラーからダブルクリック エクスプローラーの見た目と同じ
ファイル名を指定して実行 ファイル名指定時の文字と同じ(ドライブレターは必ず大文字)
コマンドプロンプトで実行 × ファイル名指定時の文字と同じ
バッチ内での外部バッチファイルを呼び出し × call文で指定した文字と同じ

参考

コマンドプロンプトを使ってみよう! -バッチファイルとは?-
バッチパラメータ・修飾子
https://ykr414.com/dos/bat.html#05