Open棟梁Project - マイクロソフト系技術情報 Wiki * 目次 [#nca91418] #contents * 概要 [#r47618c1] batファイルの勘所、debugの方法、環境変数/遅延展開、などのトピック情報を纏めています。~ batファイルはコマンドプロンプトの中で実行します。~ エクスプローラから、batファイルをダブルクリックすると、コマンドプロンプトが開いてその中で実行、終了すると、コマンドプロンプトが閉じます。~ batファイルは、コマンドプロンプトの中で、手でコマンドを逐次実行する手順を、ほぼそのままbatファイルに記述して、実行で順次実行するためのファイルです。~ コマンドプロンプトの中で、以下の様にすると、ヘルプを参照できます。~ -help -call /? -exit /? -for /? -if /? -set /? -setlocal /? -shift /? また、コマンドプロンプトそのものは、以下の様にするとヘルプを参照できます。~ -cmd.exe /? サンプルや例が必要であれば、上の様なキーワードを使用して、~ site:microsoft.com バッチファイル for の様に検索すると多数見つかります。~ コマンドそれぞれの構文については記述しません。上の様に /? をつけて実行するとヘルプが表示されます。~ コマンドプロンプトについては、以下の参照ください。~ -コマンド シェルの概要~ http://technet.microsoft.com/ja-jp/library/cc737438%28v=ws.10%29.aspx * batファイルの勘所 [#d6d50335] ** コマンドライン引数と変数 [#v8fac8e3] batファイルを呼び出すときに、引数を指定できます。 testbat.bat arg1 arg2 batファイル内では、引数は %数字 で取り出します。 echo arg1 は %1 echo arg2 は %2 batファイル内で、引数を変数に代入したり、 (set 変数名=値)~ 変数を表示したり、 (変数の場合は %変数名% で囲む)~ 変数の一部の文字を置き換えたり、 (%変数名:文字列1=文字列2%) できます。 set a1=%1 echo a1 は %a1% echo 文字置き換え %a1:g=G% %数字 は 1 から 9 まで使用できます。~ もし batファイルの引数が 10個以上必要処理する場合は、 shift を使って、%引数を 1つ前へずらします。 :_nextparam echo %1 shift if NOT "%~1" == "" goto :_nextparam :_end 引数の 数字 に 0 を指定すると、 batファイル名を取り出すことも出来ます。~ 例えば、batファイルのファイル名から拡張子違いのデータファイル名を生成するには、以下の様にします。~ set dat="%~dpn0.csv" %0 は batファイル自身を表し、~ は 次の文字に従って解釈すること指定、 dpn は ドライブ フォルダパス ファイル名 を取り出します。~ 最後に .csv をくっつけます。~ 例えば、batファイル名が、 c:\temp\test1.bat であれば、 "c:\temp\test1.csv" が 変数 %dat% に代入されます。~ batファイルでは、%変数名% は、環境変数と共通です。~ Windowsの環境変数は、コンピュータ >> プロパティ >> 詳細設定 に設定がありますが、この内容は、 batファイルから %環境変数名% で参照できます。~ ただし、 batファイルで set 環境変数名=値 を記述しても、 コンピュータ >> プロパティ >> 詳細設定 の環境変は変更されません。~ batファイル内での環境変数の変更は、batファイル内、および、batファイルから呼び出すコマンドに対してのみ効果があります。~ 引数、変数 は、 " " で囲んだまま展開されます。~ 以下のa1.batファイルがある場合、 set a=%1abc 「a1 "ABC"」 と実行すると、~ 以下の様に展開されて set a="ABC"abc set が実行され、~ 変数a に代入されます。 「"」を処理するには、 %~1 の様に 「~」 をつけて 「"」 を取り去ります。 set a=%~1abc の様にすると、以下の様に展開されて set a=ABCabc 「"」を除去できます。 更に、 set a="%~1abc" の様にすると、以下の様に展開されて、 set a="ABCabc" 余分な「"」を取り去りつつ、全体を「"」で囲むことができます。 「"」の扱いは、例えば if文 でどう記述するか、どう展開されるか、に影響します。~ batファイルが以下の場合、 if %1 == ABC ( echo ok ) 「a1 ABC」と起動すると ok ですが、~ 「a1 "ABC"」と起動すると ok になりません。 この場合、 if "%~1" == "ABC" ( echo ok ) の様にすると、 「a1 "ABC"」「a1 ABC」どちらでも ok になります。~ ** csvファイルの読み取り [#n7ed42ca] for文を使って、区切り文字(delims=)、カラム(tokens=) を指定して読み取ります。~ 下の batファイルは、csv の 2つめ 3つめ を echo します。~ また batファイルの引数に指定した 値 を 1カラム目に持つ行の 4カラム目を表示します。~ for文の ( )内は、' ' で囲んで、コマンドの出力から得ることを指定しています。 ファイル: for_3.bat @setlocal @echo off set csv="%~dpn0.csv" for /F "tokens=1,2,3,4 delims=," %%a in ('cmd.exe /c type %csv%') do ( echo %%b %%c if "%%a" == "%~1" ( echo 引数で指定されたパラメタは %%d です ) ) @endlocal 実行例 : for_3.bat 123 bbb ccc 33 44 234 456 引数で指定されたパラメタは 678 です for文に指定した %%a と tokens= に指定した数 に従って、 %%a %%b %%c ... の順に自動で変数名が使われます。 batファイルの変数は10個を超えると、shiftを使うなど、面倒が生じますが、~ 事前にパラメタを設計するようなケースでは、パラメタ情報をcsvに用意しておき、~ for文で取り出しながら、必要なバッチ処理をまとめて行う。~ というような処理も作れます。~ 上の例での注意。~ csvの値に「,」含めることは出来ません。「,」は区切り文字です。~ "aa,bbb" の様にして " で囲むことも出来ません。 上の for文は、 ( )内に type コマンドを書きましたが、下の様に ( )内にファイル名を書くこともできます。~ ただし、この場合は、" " で囲んでいないことに注意。 for /F %%a in (for_3.csv) do ( echo %%a ) ファイル名にスペースを含む場合は " " で囲みたいところですが、下の様に書くとファイル名そのものが 変数に設定されます。 for /F %%a in ("c:\temp\data files\for_3.csv") do ( echo %%a ) ** 変数の遅延展開 [#f38c6e40] for文で、 do ( ... ) の ( )内に複数行に渡って記述できますが、 ( )内で 設定した変数を使用する場合は、変数が展開されるタイミングについて注意が必要です。 @setlocal @echo off set csv="%~dpn0.csv" for /F "tokens=1,2,3,4 delims=," %%a in ('cmd.exe /c type %csv%') do ( set /A var1=%%b + %%c echo %%b + %%c は %var1% ) @endlocal 実行例: bbb + ccc は 33 + 44 は 234 + 456 は このbatファイルで、 echo の %var1% は、 for文を開始する直前に置き換えられて、空文字になっています。 以下のbatファイルの様に setlocal ENABLEDELAYEDEXPANSION を指定して 遅延展開を有効にし、 変数を !変数名! と記述します。 @setlocal ENABLEDELAYEDEXPANSION @echo off set csv="%~dpn0.csv" for /F "tokens=1,2,3,4 delims=," %%a in ('cmd.exe /c type %csv%') do ( set /A var1=%%b + %%c echo %%b + %%c は !var1! ) @endlocal 実行例: bbb + ccc は 0 33 + 44 は 77 234 + 456 は 690 遅延展開を有効にすると、!変数名! が現れた時点で値に置き換えられます。 ** 終了コード [#g160ab87] batファイルの終了コードは、exit コマンドと共に指定します。 exit /B コード ただし、exitコマンドはbatファイルが終了するので、batファイルの終了箇所で exit を使用します。 @setlocal @echo off set exitcode=0 dir c:\tempo if %ERRORLEVEL% NEQ 0 ( set exitcode=2 echo dirがエラーです ) exit /B %exitcode% @endlocal goto :EOF このbatファイルは、 exit の後にある @endlocal と goto :EOF は実行されません。~ exit /B が endlocal と goto :EOF を含んだ動作をします。 ** debug方法 [#h946982a] batファイルの効果的なdebugツールはありません。 -batファイル冒頭の @echo off をコメントアウトする -echo を随所に埋め込んで、値を表示する -pause を埋め込んで、その時点で一時停止させてみる くらいしか方法がありません。 debugが終わったら、元に戻すのを忘れないでください。 以下の様に、debug用の echo を用意すると、戻す作業が少し簡単になるかもしれません。 @setlocal @echo off call :_debugprint 引数を確認: %1 %2 %3 for /F "delims=" %%a in ('dir "%~1"') ( echo %%a ) @endlocal goto :EOF :_debugprint @rem debugが終わったら、echo をコメントアウトする echo %* goto :EOF * ちょっとしたサンプル [#rf1d958d] ** 約数を求める [#ba143095] batファイル: yakusu.bat @setlocal @echo off if "%1" == "" ( goto :_end ) set a=%1 set /A b=%a% - 1 :_next if NOT %b% GEQ 1 goto :_end set /A c=%a% / %b% * %b% if %c% == %a% ( echo %b% ) set /A b=%b% -1 goto :_next :_end @endlocal goto :EOF 実行例: yakusu.bat 32 16 8 4 2 1 以下の set /A は、割って掛けることで、割り切れる数値かを確認、をしています。 set /A c=%a% / %b% * %b% ** カレントディレクトリ以下の VC++中間ファイルを削除 [#zee2790a] batファイル: del-vc-obj.bat @setlocal @echo off call :_vcfiles @endlocal goto :EOF :_vcfiles for %%i in (*.obj *.pcb *.pch *.ncb *.pdb *.ilk *.idb) do echo "%cd%\%%i" && del "%cd%\%%i" for /D %%i in (*) do ( pushd "%%i" call :_vcfiles popd ) goto :EOF このbatファイルを実行すると、カレントディレクトリ以下のVC++の中間ファイルを全て削除します。 %cd% は コマンドプロンプトのカレントディレクトリを表す組み込みの変数です。~ 2つめのfor文でサブディレクトリを列挙して、 pushd でカレントディレクトリを記憶しつつ、サブディレクトリへ移動し、 call :_vcfiles で自身を再帰呼び出ししています。