PowerShell も浸透してきているのに今更感がありますが、リクエストを受けたので Windows バッチの機能について整理しました。
バッチファイルの拡張子は *.BAT です。
デフォルトのコマンドプロンプトの文字コードは CP932 (Microsoft版 Shift_JIS) になっています。バッチファイルも CP932 (メモ帳で保存する時は ANSI を指定) で作成する必要があります。UTF-8 のバッチファイルを実行するにはコードページ変更コマンド chcp を用います。
chcp 932 # CP932(Shift_JIS)モードにする chcp 65001 # UTF-8モードにする
バッチファイルへの引数は %1, %2, %3, ..., %9 で参照できます。%0 はコマンド名を示します。10個以上の引数を扱うには for や shift を用います。
echo コマンドは %0 です。 echo 第1引数は %1 です。 echo 第2引数は %2 です。 echo 第3引数は %3 です。
%~1 %~2 の様に % と数字の間に ~ をつけると、引数が "..." で囲まれていればそれを除去します。"C:\Program Files\..." など空白の入った文字列を渡す際に有効です。
echo "%~1"
shift [/n]
shift は引数をシフトします。shift を実行すると %2 が %1、%3 が %2 ... にシフトします。
echo %1 :1番目の引数を表示 shift echo %1 :2番目の引数を表示 shift echo %1 :3番目の引数を表示
/n を指定すると n番目の引数からシフトするようになります。例えば、/2 を指定すると %0 と %1 はそのままで、%3 が %2 に、%4 が %3 ... にシフトします。
echo %0 %1 %2 %3 %4 :0, 1, 2, 3, 4番目の引数を表示 shift /2 echo %0 %1 %2 %3 %4 :0, 1, 3, 4, 5番目の引数を表示
バッチを実行すると実行するコマンドが表示されますが、コマンドの先頭に @ をつけると表示しなくなります。
date /T :コマンドが表示される @date /T :コマンドが表示されない
echo off は以降のコマンドを表示しないようにします。@echo off を指定することで、echo off コマンド自体も表示せず、以降のコマンドも表示しなくなります。
@echo off
set set VariableName=Value set VariableName=
set は環境変数に値を設定します。
set name=Yamada
set のみを実行すると、環境変数の一覧を表示します。
set
環境変数を表示するには、環境変数名を %...% で囲みます。
echo %name%
環境変数をクリアするには下記の様にします。
set name=
setlocal [Option] endlocal Option ::= ENABLEEXTENSIONS | DISABLEEXTENSIONS | ENABLEDELAYEDEXPANSION | DISABLEDELAYEDEXPANSION
set で設定する変数はグローバル変数として設定されますが、setlocal~endlocal の間で設定される変数はローカル変数として扱われます。
set a1=123 # グローバル変数 setlocal set a2=456 # ローカル変数 echo %a1% %a2% # 両方とも参照できる endlocal echo %a1% %a2% # ローカル変数は参照できない
グローバル変数はバッチの実行完了後でもコマンドプロンプトの環境変数として残ってしまいます。
C:\>echo %name% %name% # 変数nameは未定義 C:\>test.bat # 変数nameを使用するバッチを実行 C:\>echo %name% # 変数nameの定義が残ってしまう Yamada
バッチの中で使用した変数が実行後に悪影響を与えないよう、変数を使用するバッチは startlocal...endlocal で囲んでおいた方が無難です。
@echo off setlocal : endlocal
rem Comment
rem はコメントを記載します。
rem ここにコメントを記述します
:Label
コロン(:)はラベルを定義します。ラベルは goto や call の呼び先として参照されます。
:labelA echo BBB
ラベルをコメントの代わりに使用することもできます。
:ここにコメントを記述します
goto Label
goto 文は指定したラベルの位置にジャンプします。下記の例では goto の箇所で :labelA にジャンプし、AAA と CCC が表示されます。
echo AAA goto labelA echo BBB :labelA echo CCC
call Command call :Label
call は外部コマンドや外部バッチを呼び出します。呼び出しには引数を指定することができます。
call example2.bat arg1 arg2 srg3
CALL と ラベルを用いてサブルーチンを実現することができます。
call :funcA "ABC" 123 call :funcB "XYZ" 456 exit /B 0 :funcA echo funcA(%1, %2) exit /B 0 :funcB echo funcB(%1, %2) exit /B 0
start ["Title"] [Options] Command Options ::= /D PathName /B /I /MIN /MAX /WAIT
start も外部コマンドや外部バッチを呼び出します。call とは異なり、別のコマンドプロンプトが別プロセスとして起動します。
start example2.bat arg1 arg2 arg3
"..." を指定すると、別ウィンドウのタイトルを指定することができます。
start "Some Title..." example2.bat arg1 arg2 arg3
/D オプションは別ウィンドウのカレントディレクトリを指定します。
start /D C:\Temp example2.bat arg1 arg2 arg3
/B オプションは別ウィンドウを開かずに同じウィンドウの中でコマンドを実行します。
start /B example2.bat arg1 arg2 arg3
/MIN は別ウィンドウを最小化状態で、/MAX は別ウィンドウを最大化状態で開きます。
start /MIN example2.bat arg1 arg2 arg3 start /MAX example2.bat arg1 arg2 arg3
/WAIT は start で呼び出したコマンドが終了するのを待ち合わせします。
start /WAIT example2.bat arg1 arg2 arg3
exit [/B] [ExitCode]
バッチやコマンドプロンプトを終了します。
exit
ExitCode には -2147483648~2147483647 の整数を指定することができます。
exit 123
ExitCode の値は %ERRORLEVEL% で参照することができます。
C:\> echo %ERRORLEVEL% 123
/B オプションを指定するとバッチだけが終了し、バッチを起動したコマンドプロンプトは残ります。
exit /B
if Condition Command if Condition ( Commands... ) if Condition ( Commands... ) else ( Commands... ) if Condition ( Commands... ) [else if Condition ( Commands... )]... else ( Commands... ) Condition ::= [not] [/i] Value1==Value2 [not] exist FileName [not] defined VariableName [/i] Value1 Ope Value2 Ope ::= equ | neq | gtr | geq | lss | leq
if 文は、条件式が真の時にコマンドを実行します。
set name=Yoshida if %name%==Yamada echo Yamadaです
not をつけると条件式が偽の時にコマンドを実行します。
if not %name%==Yamada echo Yamadaではありません
/i をつけると文字列比較で大文字・小文字を区別しなくなります。
if /i %name%==Yamada echo Yamadaです
name が未定義の時にもエラーにならないようにするには "..." で囲んで比較します。
if "%name%"=="Yamada" echo Yamadaです
下記の様に ( ... ) を用いることで複数のコマンドを実行することができます。
if %name%==Yamada ( echo Yamadaです echo Yamadaです ) else ( echo Yamadaではありません echo Yamadaではありません )
else if を用いることもできます。
if %name%==Yamada ( echo Yamadaです ) else if %name%==Suzuki ( echo Suzukiです ) else ( echo YamadaでもSuzukiでもありません )
数値の比較には equ などの演算子を用います。not は使用できません。
set n=10 if %n% equ 10 echo 10です if %n% neq 5 echo 5ではありません if %n% gtr 9 echo 9よりも大きな数字です if %n% geq 9 echo 9以上の数字です if %n% lss 11 echo 11よりも小さな数字です if %n% leq 11 echo 11以下の数字です
ファイルの存在有無を確認するには exist を用います。
if exist C:\Temp\test.txt echo ファイルがあります。 if not exist C:\Temp\test.txt echo ファイルが有りません。
変数が定義されているかを確認するには defined を用います。
if defined XXXX_HOME echo 定義されてます if not defined XXXX_HOME echo 定義されていません
for %%v in (files) do ( Commands ) for /R %%v in (files) do ( Commands ) for /D %%v in (directories) do ( Commands ) for /L %%v in (start, increment, end) do ( Commands ) for /F ["FOptions"] %%v in (file) do ( Commands ) for /F ["FOptions"] %%v in ('Command') do ( Commands ) FOptions ::= delims=string tokens=n, ... skip=n eol=string usebackq
for文は対象のファイル群に対してループ処理を行います。変数名は1文字に限られます。ファイルは空白デリミタで複数指定できます。
for %%f in (*.txt) do ( echo %%f )
/R を指定するとサブフォルダを含めて再帰的にファイルを検索します。
for /R %%f in (*.txt) do ( echo %%f )
/D を指定するとファイルではなくディレクトリを対象に処理を行います。
for /D %%d in (a*) do ( echo %%d )
下記の様にするとコマンド引数に対してループ処理を行います。
for %%a in (%*) do ( echo %%a )
/L を指定すると N回ループを実現できます。(...) の中には、初期値、増分、終了値を指定します。
for /L %%n in (1, 1, 10) do ( echo %%n )
/F を指定すると (...) で指定したファイルの中身の1行1行に対してループを実行します。
for /F %%a in (xx.csv) do ( echo %%a )
delims はトークンの区切り文字、tokens は参照するトークン番号を指定します。下記の例では区切り文字に , を指定し、第1トークンを %%a、第2トークンを %%b として参照します。
for /F "delims=, tokens=1,2" %%a in (sample.csv) do ( echo %%a / %%b )
skip は先頭行から指定した行数分無視します。下記の例では CSV ファイルの先頭行をヘッダ行とみなして無視します。
for /F "skip=1 delims=, tokens=1,2" %%a in (sample.csv) do ( echo %%a / %%b )
eol は指定した文字で始まる行を無視します。下記の例では # で始まる行をコメント行とみなして無視します。
for /F "eol=#" %%a in (sample.txt) do ( echo %%a )
/F 指定時にファイル名を '...' で囲むと、... で指定したコマンドの実行結果の1行1行に対してループを実行します。
for /F %%a in ('dir /b') do ( echo %%a )
usebackq はコマンドの実行結果を処理する際に '...' の代わりにバッククォート `...` をしようします。
for /F "usebackq" %%a in (`dir /b`) do ( echo %%a )
FOR文の中で変数を参照するには注意が必要です。下記の様にループの中で %name% を参照しても最初に FOR文を評価する時点で変数が展開されてしまうためうまく参照できません。
for /L %%n in (1, 1, 3) do ( set name=Yamada%%n echo My name is %name% )
この問題を解決するにはループを setlocal enabledelayedexpansion ... endlocal で囲み、変数参照時の % を ! に変更することで、FOR文実行時に遅延展開させることができます。
setlocal enabledelayedexpansion for /L %%n in (1, 1, 3) do ( set name=Yamada%%n echo My name is !name! ) endlocal
配列はサポートされていませんが、変数名に [ や ] も使用できるので、配列っぽく見せることはできます。下記は正確には配列ではなく、a[0] という名前の変数を定義して参照しています。
set a[0]=foo set a[1]=baa set a[2]=baz echo %a[0]% # foo echo %a[1]% # baa echo %a[2]% # baz
call を用いると変数が展開されることを利用して、下記の様にループの中で変数名を生成することもできます。
set a[0]=foo set a[1]=baa set a[2]=baz for /L %%i in (0, 1, 2) do ( call echo a[%%i]=%%a[%%i]%% )
コマンドを検索する対象フォルダのリストを保持します。デリミタはセミコロン(;)です。
Path=C:\Windows;C:\Windows\system32;
直前に終了したコマンドの終了コードを示します。通常、0 は成功、0 以外はエラーを意味します。
if %errorlevel% == 0 ( echo OK ) else ( echo NG )
コマンドプロンプトを指定します。
set PROMPT=$P$G
$N 現在のドライブ名。 $P 現在のドライブ名とパス名。 $D 現在の日付。 $T 現在の時刻。 $V Windowsバージョン。 $A アンパサンド(&)。 $B パイプ記号(|)。 $L 小なり不等号(<) $G 大なり不等号(>) $Q 等号(=) $F 右括弧()) $C 左括弧(() $H バックスペース(BS) $$ ドル記号($) $S 半角スペース( ) $E エスケープコード(\x1B) $_ 改行文字(CR LF)
0~32767 の乱数を発生させます。
echo %RANDOM% 18703
CommonProgramFiles # 共通プログラムフォルダ(例:C:\Program Files\Common Files) CommonProgramFiles(x86) # 共通プログラムフォルダ(32ビット用)(例:C:\Program Files (x86)\Common Files) CommonProgramW6432 # 共通プログラムフォルダ(32/64ビット共用)(例:C:\Program Files\Common Files) COMPUTERNAME # コンピュータ名(例:MYCOMPUTER) ComSpec # コマンドプロンプトプログラム(例:C:\WINDOWS\system32\cmd.exe) DriverData # ドライバデータフォルダ(例:C:\Windows\System32\Drivers\DriverData) HOMEDRIVE # ホームドライブ(例:C:) HOMEPATH # ホームフォルダのパス名(例:\Users\tanaka) LOCALAPPDATA # アプリケーションデータフォルダ(例:C:\Users\tanaka\AppData\Local) LOGONSERVER # ログオンサーバ名(例:\\MYCOMPUTER) NUMBER_OF_PROCESSORS # プロセス数(例:12) OneDrive # OneDriveのパス名(例:C:\Users\tanaka\OneDrive) OneDriveConsumer # OneDriveの個人アカウントパス(例:C:\Users\tanaka\OneDrive) OS # OS種別(例:Windows_NT) PATHEXT # 実行可能ファイルの拡張子(例:.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC) PROCESSOR_ARCHITECTURE # プロセッサアーキテクチャ(例:AMD64) PROCESSOR_IDENTIFIER # プロセッサ識別子(例:Intel64 Family 6 Model 165 Stepping 5, GenuineIntel) PROCESSOR_LEVEL # プロセッサレベル(例:6) PROCESSOR_REVISION # プロセッサリビジョン(例:a505) ProgramData # プログラムデータフォルダ(例:C:\ProgramData) ProgramFiles # プログラムフォルダ(例:C:\Program Files) ProgramFiles(x86) # プログラムフォルダ(32ビット用)(例:C:\Program Files (x86)) ProgramW6432 # プログラムフォルダ(32/64ビット共用)(例:C:\Program Files) PSModulePath # PowerShellモジュール(例:C:\Program Files\WindowsPowerShell\Modules) PUBLIC # パブリックフォルダ(例:C:\Users\Public) SESSIONNAME # セッション名(例:Console) SystemDrive # システムドライブ名(例:C:) SystemRoot # システムルートフォルダ(例:C:\WINDOWS) TEMP # テンポラリフォルダ(例:C:\Users\tanaka\AppData\Local\Temp) TMP # テンポラリフォルダ(例:C:\Users\tanaka\AppData\Local\Temp) USERDOMAIN # ユーザドメイン(例:MYDOMAIN) USERNAME # ユーザ名(例:tanaka) USERPROFILE # ユーザプロファイルフォルダ(例:C:\Users\tanaka) windir # Winodwsフォルダ(例:C:\WINDOWS)