マイクロソフト系技術情報 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。

目次

概要

UNIX系オペレーティングシステムのシェルスクリプトに相当する。

詳細

  • 以下のようなトピック情報を纏めています。
    • batファイルの勘所
    • debugの方法
    • 環境変数/遅延展開

実行方法

  • batファイルは、
    • CMDで、手でコマンドを逐次実行する手順を、
      ほぼそのまま、batファイルに記述して、
    • 実行で順次実行する

ためのファイルです。

  • batファイルはCMDの中で実行します。
    • エクスプローラ上でダブルクリックすると、
    • CMDが開いて、その中で実行、
    • 終了すると、CMDが閉じます。

ヘルプ、サンプル

ヘルプ

コマンドそれぞれの構文については記述しません。
コチラの様に /? をつけて実行するとヘルプが表示されます。

サンプル

サンプルや例が必要であれば、
コチラの様なキーワードを使用して、

 site:microsoft.com バッチファイル for

の様に検索すると多数見つかります。

勘所

コマンドライン引数と変数

引数の指定

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

batファイル名

  • 引数の 数字 に 0 を指定すると、 batファイル名を取り出すことも出来ます。
    • 例えば、batファイルのファイル名から拡張子違いのデータファイル名を生成するには、以下の様にします。
    • batファイル名が、 c:\temp\test1.bat であれば、 "c:\temp\test1.csv" が 変数 %dat% に代入されます。
       set dat="%~dpn0.csv"
  • %0 は batファイル自身を表し、
  • は 次の文字に従って解釈すること指定、

  • dpn は ドライブ フォルダパス ファイル名 を取り出します。
  • 最後に .csv をくっつけます。

変数と環境変数

batファイルでは、%変数名% は、環境変数と共通です。

  • Windowsの環境変数は、
    • コンピュータ >> プロパティ >> 詳細設定 に設定があります。
    • この内容は、 batファイルから %環境変数名% で参照できます。
  • batファイル内での環境変数は、
    • 下記でのみ、参照できます。
      • batファイル内、
      • および、batファイルから呼び出すコマンド
  • set 環境変数名=値 を記述しても、
    コンピュータ >> プロパティ >> 詳細設定 の環境変数は変更されません。

「"」の除去

引数、変数 は、 " " で囲んだまま展開されます。

以下の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ファイルの読み取り

for文を使って、区切り文字(delims=)、カラム(tokens=) を指定して読み取ります。

下の batファイルは、csv の 2つめ 3つめ を echo します。
また batファイルの引数に指定した 値 を 1カラム目に持つ行の 4カラム目を表示します。
for文の ( )内は、' ' で囲んで、コマンドの出力から得ることを指定しています。

batファイル:

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
 )

変数の遅延展開

遅延展開 無効

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

遅延展開を有効にすると、!変数名! が現れた時点で値に置き換えられます。

終了コード

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方法

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

サンプル

約数を求める

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++中間ファイルを削除

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% はCMDのカレントディレクトリを表す組み込みの変数です。
2つめのfor文でサブディレクトリを列挙して、 pushd でカレントディレクトリを記憶しつつ、
サブディレクトリへ移動し、 call :_vcfiles で自身を再帰呼び出ししています。

参考

知識ゼロからのwindowsバッチファイル超入門

https://jj-blues.com/cms/

Qiita

@IT


Tags: :シェル, :インフラストラクチャ, :Windows


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2020-05-12 (火) 09:46:56 (17d)