コマンドプロンプトでバッチ処理を行うときの覚え書き

 コマンドプロンプトは、Windowsで標準装備されているCUIベースのプログラム実行環境で、バッチファイルと呼ばれる、拡張子が「.bat」であるテキストファイルに簡単なプログラミング(コマンドの実行手順を記述すること)で定型的な処理の自動化を実現することができます。
 バッチファイルによる処理のメリットは、途中に人手を介さない(たとえば、多量のファイルコピーなどの)処理は、ほぼ完全に自動で行えることで、手作業の負担を減らすことができます。
 (通常のGUIのプログラムのように、処理対象となるファイル名の選択や、ウィンドーサイズの変更、処理オプションの設定などは、バッチ処理では普通行いません。)
 ここには、Windows 2000以降に拡張されたコマンドを中心に度忘れしそうな事柄や汎用的に使えそうなスクリプトの雛形などを置いておくことにします。
 あまり役に立たないかも知れませんが、自由に利用してください。

バッチコマンドについて

 コマンドの詳細な説明は、「コマンド /?」 で表示できます。
例)dir /?
 以下のバッチ(例えば、help.batとする)を実行すると、入力したコマンドの説明をファイルに残せるので便利かも...
(メモ帳を起動し、下の2行を入力して「help.bat」という名前で保存します。)
set /p cmd=コマンド名:
%cmd% /? >%cmd%.txt 2>&1
(「help.bat」をダブルクリックしてコマンド名を入力すると、コマ ンドの説明がテキストファイルで保存されるので、作成されたファイルをメモ帳などで開いて説明を読みます。)

SETコマンド

SETコマンドは、環境変数を設定したり削除できますが、その他に計算やキーボード入力を受け付けることも出来ます。
使い方)

●環境変数の設定と削除
SET src="C:\Documents and Settings\PC-user\My Documents\C\Source" → 変数の設定
SET src=  → 変数の削除
●計算
SET /A x += 1 → 計算
(この場合、SET /A x = y + z のように右辺の環境変数を「%y%」と括らなくてもかまいません。)
SETコマンドで使える計算記号(演算子)
  ( ) :グループ化 (x + y) * 2
  ! :論理否定(!0→1, !0以外の数→0)
  ~ :ビット反転(~0→-1, ~3→-4)
  - :マイナス符号(-1, -z)
  * :乗算(掛け算:5*3→15)
  / :除算(割り算:5/3→1)
  % :剰余(余り:9%%4→1)
  + :加算(足し算:5+3→8)
  - :減算(引き算:5-3→2)
  << :ビット左シフト(5^<^<3→40)
  >> :ビット右シフト(13^>^>2→3)
  & :ビット論理積(6^&5→4, 6^&3→2)
  | :ビット論理和(6^|5→7, 6^|3→7)
  ^ :ビット排他的論理和(不一致論理:6^^5→3, 6^^3→5)
  = :代入(転記:s=5+3→8, z=5-3→2)
  += :加算代入(z+=3→z=z+3)
  -= :減算代入(z-=3→z=z-3)
  *= :乗算代入(s*=5→s=s*5)
  /= :除算代入(s/=5→s=s/5)
  %= :剰余代入(s%%=5→s=s%%5)
  <<= :左シフト代入(s^<^<=5→s=s^<^<5)
  >>= :右シフト代入(s^>^>=5→s=s^>^>5)
  &= :論理積代入(s^&=5→s=s^&5)
  |= :論理和代入(s^|=5→s=s^|5)
  ^= :排他的論理和代入(s^^=5→s=s^^5)
※SETコマンドでは、原則、整数計算なので割り算などの小数は「切り捨て」となります。
※特殊記号「& | < > ^」は、記号の前に「^」記号を追加する必要があります。
  (詳細は「リダイレクトとパイプ」を参照ください。)
●キーボードからの入力
SET /P f=ファイル名を入力してください: → キーボード入力
なお、漢字・ひらがなを入力するには[ALT]+[半角/全角]([ALT]を押した状態で[半角/全角]を押します。)で「ローマ字かな入力」モードにできます。
ローマ字かな入力を抜けるには、もう一度、[ALT]+[半角/全角]を押します。
SET /P の応用として、改行しないで文字列を表示させる(ECHOの代用とする)こともできます。
SET /P ダミー変数=表示文字列<nul (例: SET /P dummy=%var% < NUL)
さらに、SETコマンドでの使用に限りませんが、Windows2000以降では、パラメータの引数や環境変数の加工などの機能が大幅に強化されていて様々な処理をバッチファイルだけで実現できるようになっています。
コマンド引数の編集/加工
  %~番号:指定番号の引数の先頭と最後に現れる「"」を削除して扱います。
    「"」で始まらない場合は引数の値がそのまま使われます。
    例 "my documents" → my documents

  %~f番号:指定番号の引数の値をフルパスのファイル名にします。
    例 20130909.txt → C:\Users\ユーザー名\Documents\logs\20130909.txt
  %~d番号:指定番号の引数の値からドライブ名を取り出します。
    ドライブ名が指定されていない場合は、カレントドライブの指定となります。
    例 c:20130909.txt → C
  %~p番号:指定番号の引数の値からパス(ドライブとファイル名を除いたフォルダ名の部分)を
    取り出します。
    例 C:\Users\ユーザー名\Documents\logs\20130909.txt → \Users\ユーザー名\Documents\logs\
  %~n番号:指定番号の引数の値から拡張子を除いたファイル名部分を取り出します。
    例 C:\Users\ユーザー名\Documents\logs\20130909.txt → 20130909
  %~x番号:指定番号の引数の値からファイル名の拡張子部分を取り出します。
    例 C:\Users\ユーザー名\Documents\logs\20130909.txt → .txt
  %~a番号:指定番号の引数の値に対応するファイルが存在する場合、そのファイルの属性
    「アトリビュート」を取り出します。
    例 C:\Users\ユーザー名\Documents\logs\20130909.txt → --a------
  %~t番号:指定番号の引数の値に対応するファイルが存在する場合、そのファイルの参照
    時刻を取り出します。
    例 C:\Users\ユーザー名\Documents\logs\20130909.txt → 2013/09/09 01:23
  %~z番号:指定番号の引数の値に対応するファイルが存在する場合、そのファイルのサイズ
    (byte数)を取り出します。
    例 C:\Users\ユーザー名\Documents\logs\20130909.txt → 345
  %~s番号:指定番号の引数の値に対応するファイルが存在する場合、そのファイルのショート
    形式のフルパスを与えます。
    例 C:\Users\ユーザー名\Documents\logs\20130909.txt → C:\Users\ユーザー~1\DOCUME~1\logs\20130909.txt
  %~nx番号:指定番号の引数の値に対応するファイルのファイル名と拡張子を取り出します。
    例 C:\Users\ユーザー名\Documents\logs\20130909.txt → 20130909.txt
  %~dp番号:指定番号の引数の値に対応するファイルのドライブ名とパスを取り出します。
    例 C:\Users\ユーザー名\Documents\logs\20130909.txt → C:\Users\ユーザー名\Documents\logs\
※コマンド引数についての概要はCALLコマンドの説明(CALL /?)で見ることができます。
※コマンド引数の機能を積極的に使うには「CALL :sub 引数1 引数2 ・・・ 引数n → (:sub) set p=%~z1」などとしてバッチ内サブルーチンを利用します。
※コマンド引数のファイル名を「"」で括った場合(例:"file.txt")%~a番号、%~t番号、%~z番号が正常に機能しないことがあります。
環境変数の編集/加工
  %変数名%:環境変数を展開します。
    例 Windows7の場合、echo %date% → 2013/09/09

  %変数名:~開始位置,文字数%:文字列中の開始位置から指定の文字数を取り出します。
    開始位置が負の数であれば、最後の文字から数えた位置を使います。
    また、文字数が省略された場合は、開始位置以降のすべての文字を取り出します。
    例 echo %date:~0,4% → 2013、echo %date:~-5% → 09/09
  %変数名:検索文字列=置換文字列%:検索文字列に一致する部分を置換文字列に置き換えます。
    例 echo %date:/=-% → 2013-09-09
※環境変数についての概要はSETコマンドの説明(SET /?)で見ることができます。
※バッチファイルでの文字列の加工・編集には、コマンド引数、環境変数を「for /F」コマンドなどと連携して操作することを考えるとよいでしょう。

ECHO で改行だけをさせるには

ECHO. ECHO= ECHO: ECHO/ ECHO+ など ECHO の直後に記号を入れることで改行動作だけを行うことができます。
また、バッチファイル内では、ECHO.%var% などと記述すると%var%が設定されていればその値を、空のときには改行動作だけを行わせることができます。

リダイレクトとパイプ

●リダイレクト
リダイレクトは、標準入力(通常はキーボード)や標準出力(通常はディスプレイ)をファイルに割り当てる仕組みで「<」記号でファイルから標準入力へ「>」または「>>」記号で標準出力をファイルへ接続します。
「>」は出力ファイルを常に新規作成しますが、「>>」は既存のファイルが存在する場合には、データの追加動作となります。
また、2>ファイル名 とすることで、標準エラー出力(エラーの画面表示)をファイルに書き出すこともできます。
例)標準入力をファイルに割り当てます。
   find "パソコン" <data.txt または find "パソコン" 0<data.txt
例)標準出力をファイルに割り当てます。
   echo "コマンドプロンプト" >new.txt または echo "コマンドプロンプト" 1>new.txt
例)追加モードでファイルに出力します。
   echo "パソコン、プリンタ" >>new.txt または echo "パソコン、プリンタ" 1>>new.txt
例)標準出力と標準エラーをまとめて1つのファイルに書き出します。
   dir /? 1>bat.log 2>&1
(2>&1 で標準エラーを標準出力につなぎます。)
上記の例から分かるとおり
 標準入力の装置番号=0
 標準出力の装置番号=1
 標準エラー出力の装置番号=2
となっています。

●パイプ
パイプは、コマンドの標準出力を次のコマンドへの標準入力につなぐ仕組みです。
例)type data.txt|more
(type コマンドで data.txt の内容を読み出して more に引渡し、ページ(画面)単位で表示します。)

【参考】
バッチファイルでリダイレクト記号(<, >)やパイプ記号( | )を通常の記号として使いたい場合は、「^」でエスケープできます。
例えば、HTMLのタグを記述するには、「^<p^>」のようにします。
また、その他の特殊記号についても「^\」「^%」「^!」「^"」「^&」「^^」などと記述して特殊記号の機能を無効にすることができます。

IFコマンド

 ifコマンドは、与えられた条件を判断(評価)して処理を切り替えるコマンドです。
コマンドプロンプトのifコマンドは比較的簡単な条件判断しかできませんが、処理を切り替えるための重要なコマンドとなっています。
●ifコマンドの構文
IF 条件 コマンド
IF 条件 コマンド ELSE コマンド
IFコマンドの条件文
"文字列/変数" 条件演算子 "文字列/変数"
変数/数値 条件演算子 変数/数値
【条件演算子】
GTR (左の数値)が(右の数値)より大きい ・・・・・ IF %p% GTR 0 コマンド
LSS (左の数値)が(右の数値)より小さい ・・・・・ IF %p% LSS 1 コマンド
GEQ (左の数値)が(右の数値)以上 ・・・・・・・・ IF %p% GEQ 0 コマンド
LEQ (左の数値)が(右の数値)以下 ・・・・・・・・ IF %p% LEQ 1 コマンド
EQU (左の数値)が(右の数値)と等しい ・・・・・・ IF %p% EQU 1 コマンド
== (左右の文字列)が等しい ・・・・・・・・・・・・・・・ IF "%p%" == "" コマンド
NEQ (左右の数値)が等しくない ・・・・・・・・・・・・・ IF %p% NEQ 0 コマンド
NOT (右の論理値)でない ・・・・・・・・・・・・・・・・・ IF NOT "%p%" == "" コマンド
DEFINED (変数が)定義されている=値を持っている ・・・ IF DEFINED %f% コマンド
EXIST (右で指定された)ファイルが存在する ・・・・・・・・・・・ IF EXIST %f% コマンド
ERRORLEVEL 数値(%ERRORLEVEL%の値)が数値以上 ・・ IF ERRORLEVEL 1 コマンド

コマンドのブロック化

コマンドプロンプトでは、複数のコマンドをひとまとめにして処理をすることができます。
●パイプ
|」 パイプによる連続処理
   例)find "," myfile.txt|more
パイプ処理を使うことで、前段の標準出力を次の処理への標準入力につなぐことができます。
●コマンドの連結
複数のコマンドを「&」で区切ることで、コマンドを連結して実行できます。
   例)pushd & cd .. & dir & popd
   「&」の前後にスペースを入れるとスペースを含めてコマンドを解釈するようです。
   そのため、「&」の前後にスペースは入れないほうが良いようです。
●処理ブロック:( )
( ) によるブロック化(バッチ用)
   例)
   if ERRORLEVEL 1 (
       echo コマンドの実行に失敗しました。
       echo ファイル「%FL%」が存在するか、確認してください。
       rem goto :EOF でバッチ処理を終了します。
       goto :EOF
   )
( )ブロックを使う場合は、( )内全体が1つの行とみなされるため、環境変数は( )ブロックに入った時点で展開されることに注意が必要です。
特にIFコマンドでは、IF 条件 ( 真ブロック ) ELSE ( 偽ブロック )まですべてが一度に展開されるので、思いがけない実行結果になることがあります。
適宜、ECHOコマンドなどで環境変数をチェックしましょう。

FORコマンドは、いろいろな使い方ができます。

●for %%変数 in (ファイルリスト) do コマンド
ファイルリストに含まれるファイル名を1つづつ %%変数(FOR変数)に取り出し、コマンドを実行します。
バッチで for を使うときは、FOR変数を %%変数 のように % を2つ並べなければなりません。
例)for %%I in (*.txt *.dat) do findstr "日本.+技術" %%I
 これは、カレントディレクトリ(現在、操作対象となっているフォルダ)内にある拡張子が「.txt」または「.dat」であるファイルを取り出し、そのファイルに含まれる「日本」で始まり「技術」で終わる文字列を表示します。
 ※FOR変数は、英字1文字で指定します。
 (a~z、A~Zしか使えず、aとAは別の変数として扱われます。)

●for /D %%変数 in (ファイルリスト) do コマンド
ファイルリスト中のサブディレクトリ(サブフォルダー)だけを取り出しコマンドを実行します。
 ※ファイル名は取り出しません。
この書き方は、ディレクトリ単位で(ファイルのコピーや削除などの)処理を行うのに向いています。

●for /R ドライブ:パス %%変数 in (ファイルリスト) do コマンド
ドライブ:パスで指定されたディレクトリーから順にサブディレクトリを検索し、ファイルリストに指定されたファイル名に一致するものを%%変数に取り出し てコマンドを実行します。
少しわかりにくい表現なので、類似の処理を書いてみます。
ファイルの一覧表示で、「DIR」コマンドのオプション指定を
dir /S /B c:\users\ユーザー名\Documents\*.txt
とすると、サブディレクトリーのファイルも含めて拡張子が「txt」のファイルを表示することができます。
これと類似の処理を「for /R 」で表現すると
for /R c:\users\ユーザー名\Documents %%f in (*.txt) do echo %%f
となります。
サブディレクトリを含めて処理を行いたい場合は比較的多いと思いますが、以下のテンプレートが参考になるかもしれません。
テンプレート:
   for /R c:\users\ユーザー名\Documents %%f in (*.txt *.log) do call :sub %%f
     |
   :sub
   コマンド %1
   exit /b
(もう一つの方法:for /F を使う方法)
   for /F "usebackq" %%f in (`dir /S /B "c:\users\ユーザー名\Documents\*.txt"`) do echo %%f
でも同等の処理が可能です。
どの方法を使うかは、お好みで決めればよいと思います。
「for /R」の使用例:
ドキュメント以下のサブフォルダも含めて「使い方」という文字列を含み、拡張子が「txt」であるファイルの個数を調べます。
set /a n=0
for /R "%userprofile%\documents" %%f in (*.txt) do call :sub %%f
echo %n% 個
del %t%
pause
exit /b
:sub
set r=
set t=%~dp0temp%date:/=%.tmp
findstr "使い方" %1 > %t%
set /p r= < %t%
if NOT "%r%" == "" set /a n += 1 & call echo %r%
exit /b
※このバッチは、Windows7のみで動作を確認しています。
 Windows XP では
 for /R "%userprofile%\my documents" %%f in (*.txt) do call :sub %%f
 としてください。

●for /L %%変数 in (開始数, 増加数, 終了数) do コマンド
開始数、増加数、終了数で指定される回数でコマンドを繰り返します。
%%変数には、開始数、増加数で計算された数が設定されます。
例)
for /L %%I in (1, 1, 10) do echo %%I → 1~10までの数字を表示します。
for /L %%I in (10, -3, -1) do echo %%I → %%Iの値を10、7、4、1と10から3づつ引き算して行き、結果が-1以上(-1を含む)なら%%Iを表示します。

●for /F "オプション" %%変数 in (ファイルリスト) do コマンド
ファイルリストに含まれるファイルから行を読み出し、指定の区切り符号までのデータ(文字列)を%%変数に取り出してコマンドを実行します。
※指定のファイルから行単位でデータを読み出して処理を行えます。
オプション
eol:行の終了を表す文字を指定します。例えば、「eol=#」とすることで、「#」で始まる行をコメント行とみなします。
skip:ファイルの先頭から読み飛ばす行数を指定します。
tokens:区切り符号で分割された文字列の位置を指定して取り出します。(指定しなければ1番目)
"tokens=2,4-6*" %%D とすると、%%D に2番目の文字列、 %%E に4番目、 %%F に5番目、 %%G に6番目、 %%H に残りのすべての文字列が設定されます。
なお、%%E、%%F、%%G、%%Hは暗黙で自動的に作成される変数です。
delims:区切り符号を変更します。(指定しなければ、半角空白(スペース)です。)
区切り符号を無効にするには、"skip=1 delims=" のように「"」の直前にdelims=を記述します。
例)for /F "tokens=* delims=" %%L in (access.log) do set /a ln+=1
tokens=* で行全体を %%L に取り込みます。delims=で区切り符号を無効にします。
この処理で 「access.log の行数」を環境変数lnに求めます。

●for /F "オプション" %%変数 in ('コマンド') do コマンド
'コマンド'の出力結果から指定の区切り符号までの文字列を%%変数に取り出してdo コマンドを実行します。
'コマンド 引数1 引数2 ・・・ ' という形で引数を与えることができますが、'コマンド "文字列"' という形の引数を与えることはできません。
例えば、
for /F %%c in ('dir /B /ON C:\ユーザー\user\ドキュメント\backup\*.c') do copy %%c D:\backup
は、期待通りの動作をするはずですが、
for /F %%c in ('dir /B /ON C:\Documents and Settings\ユーザー\マイ ドキュメント\c\*.c') do copy %%c D:\backup
は、フォルダー名に空白(間隔)文字が含まれているため期待する動作とはならないはずです。
引数を「" "」で括りたい場合は、下の「`コマンド`」構文を使います。
例)for /F "tokens=* delims=" %%I ('type cpy.lst') do copy %%I myfolder
cpy.lst から読み出されたファイル名に該当するファイルだけ myfolder にコピーします。
オプションは、上に同じ

for /F "オプション" %%変数 in ("文字列") do コマンド
文字列をファイルからの入力行として%%変数に取り出してコマンドを実行します。
オプションは上に同じ
例)for /F "tokens=1-3 delims=/" %%D in ("%date%") do echo %%D年%%E月%%F日
 日付の形式を「2013/09/09」から「2013年09月09日」に変更します。
※この形は、バッチファイルの文字列加工、文字列編集にも有効に使うことができます。
 ここでは参考のために、「CSV(項目間をコンマ「,」で区切る)形式」の行データから指定位置の項目文字列を取り出すサブルーチンを示します。
例)文字列抽出
@echo off

set data=T031001,123 ドライバーセット,+2,Red,480,22
set sep=,
set /a p=2
echo call :drip "%data%" "%sep%" %pos%

call :drip "%data%" "%sep%" %p%
echo res=%res%
echo on
exit /b

rem [呼び出し方] call drip "文字列" "区切り文字" 取り出し位置
:drip
   set drip_str=%~1
   set drip_delim=%~2
   set /a drip_pos=%~3
   if %drip_pos% LSS 1 set /a drip_pos=1
   if %drip_pos% GTR 32 (
      echo 取り出し位置は 1 ~ 32 の範囲で指定してください。
      set res=%drip_str%
      goto :EOF
   )
   for /f "tokens=%drip_pos% delims=%drip_delim%" %%V in ("%drip_str%") do set res=%%V
   goto :EOF


●for /F "usebackq オプション" %%変数 in (`コマンド "文字列"`) do コマンド
`コマンド "文字列"` を実行し結果の文字列を区切り符合で分割して変数に取り出し、do コマンドを実行します。
オプションは上に同じ
この構文では、`コマンド`の引数に"文字列"を与えることができます。
例)for /F "usebackq tokens=*" %%I in (`dir /b /a-d "my music"`) do set /a n+=1

CALLコマンド

従来のCALLコマンドは外部のバッチファイルを読み込んでサブルーチンとして実行するものでしたが、現在はラベルを指定して、 バッチファイル内に記述したサブルーチンを呼び出すことも出来るようになっています。
サブルーチンから呼び出し元にもどるときに、「EXIT /B 整数」や「EXIT 整数」と記述することで、整数値を返すことが出来ます。
※EXIT /B と EXIT の違いは、EXIT /B ではサブルーチンの呼び出し元のバッチ処理に制御を戻すのに対して、EXIT では、制御を呼び出し元に戻さずバッチ処理を終了してしまうことです。
例)
if "%obj%" == "" CALL :obj


:obj
 set /p obj=OBJのパスを入力してください。: 
 if "%obj%" == "" set obj="%HOMEDRIVE%%HOMEPATH%\My Documents"
exit /b

※バッチ処理やサブルーチンを終了させるには「GOTO :EOF」という記法もあります。

環境変数の展開
call コマンドは、環境変数の展開(評価)が2回行われることを利用して、環境変数の遅延展開や配列風の使い方に応用することができます。

あまり良い例ではありませんが、
set /A y = 0
for /L %%N in (1, 1, 10) do set /A y = 3 - y & call echo %%y%%
ここでは、forコマンド内のyの値(3と0の繰り返し)を表示させています。
同様の計算で、
set /A x = 0
for /L %%N in (1, 1, 100) do set /A x = (x + 15) %% 16 & call echo %%y%%
こちらは、xの値(15から0の繰り返し)を表示させています。

次に、環境変数を連想配列(hash:ハッシュ)のように使ってみます。
set c[name]=PC-9801RX2
set c[cpu]=Pentium-X(128bit, 40GHz)
set c[mem]=4TB
set c[price]=5800
set p=cpu
call echo %%c[%p%]%%
この例では「Pentium-X(128bit, 40GHz)」の文字が表示されます。
また、
set array[1][1]=2
set array[1][2]=4
set array[2][1]=5
set array[2][2]=0
set x=2
set y=1
call echo %%array[%y%][%x%]%%
では、環境変数を通常の配列のように扱うことができます。 この場合は「4」が表示されます。
さらに、環境変数の文字列の置き換えやファイルスペックの参照にも callコマンド が応用できます。
(例1)
set s=テスト文字列
set t=テスト
set r=日本語
call set s=%%s:%t%=%r%%%
echo %s%
exit /b
この例では、環境変数 s の内容(テスト文字列)を「日本語文字列」に変更しています。
(例2)
set n=%~0
call :fspec %n% z
exit /b
:fspec
set fspec=%~2
call echo %%~%fspec%1
goto :EOF
こちらは、自分自身のファイルサイズを表示します。

「or、and」による複合条件の判定
callコマンドを使ってifコマンドでは難しかった複合条件の判定を行わせることができます。
複合条件の判定方法
call :or "判定条件1" "判定条件2"
if %stat% GTR 0 コマンド
call :and "判定条件1" "判定条件2"
if %stat% GTR 0 コマンド
call :xor "判定条件1" "判定条件2"
if %stat% GTR 0 コマンド
 ・
 ・
exit /b
rem -----------------
rem or=どちらかが1(真)なら1(真)を返します。両方1(真)のときも1(真)、両方0(偽)のときだけ0(偽)です。
:or
set /a stat=0
if %~1 set /a stat=1
if %~2 set /a stat=1
exit /b
rem and=どちらかが0(偽)なら0(偽)を返します。両方0(偽)のときも0(偽)、両方1(真)のときだけ1(真)です。
:and
set /a stat=1
if NOT %~1 set /a stat=0
if NOT %~2 set /a stat=0
exit /b
rem xor=どちらか一方が1(真)で、もう一方が0(偽)のとき1(真)を返します。両方1(真)または両方0(偽)のときは0(偽)となります。
:xor
set /a stat=0
if %~1 set /a stat=1
if %~2 set /a stat=stat^^1
exit /b
rem ------------------
判定条件には、ifコマンドの条件を「"」で括って記入します。
(例)call :or "%s% GTR 100" "%s% LEQ 10"
判定の結果は、%stat%に0(偽:失敗)、1(真:成功)として返されます。
判定条件を call :and "NOT %s% GTR 100" "NOT %s% LEQ 10"
call :or "NOT %s% GTR 100" "NOT %s% LEQ 10"
のように設定することでNOT_AND(NAND)やNOT_OR(NOR)の判定もできます。
複雑な条件判定でも条件を何段階かに分割することで対応できるでしょう。

PUSHDとPOPD

コマンドプロンプトを使うときにカレントディレクトリ(基準となる現在のディレクトリ)を一時的に変更したい場合があります。
こんなときは、
PUSHD → 現在のディレクトリをスタック(システムが用意している退避領域)に保存します。
  「PUSHD ディレクトリ」とすることで指定のディレクトリに移動することもできます。
POPD → スタック(システムが用意している退避領域)に保存したディレクトリを取り出してそこに移動します。
バッチファイルで、バッチファイルの存在するディレクトリをカレントディレクトリ(実行時のディレクトリ)に指定するには、
pushd %~dp0
rem 「%~dp0」は、バッチファイルの存在するd:ドライブとp:ディレクトリーを取り出します。
:
popd
exit /b
のように記述します。

ページトップへ戻る

バッチ処理がうまく動かないとき

コマンドのつづりが間違っているとか文法(使い方)が間違っている場合は、実行時にエラーメッセージが出ますからこれを確認します。
「ファイルが見つかりません。」などのバッチの実行フォルダが問題になる場合には「PUSHD %~dp0」を入れてみてください。
エラーはでないけれど実行が途中で止まる、または結果がおかしい場合は、適宜 echo on を入れて動作の状況を確認します。
どうしても、エラーが見つからないときは、
| や & や ( ) による処理のブロック化 および FORコマンド内での変数の取り扱いを見直してみてください。
●処理ブロック内の環境変数の展開
例えば、次の上と下の処理はどちらも正常に(エラーとならず)実行されますが、下の記述は期待する動作にはならないでしょう。
rem ----+----1----+----2----+----3----+----4----+----5----+----
set par=
if "%par%" == "" set /p par=引数を設定してください:
if "%par%" == "" goto :EOF

rem ----+----1----+----2----+----3----+----4----+----5----+----
set par=
if "%par%" == "" (
set /p par=引数を設定してください:
if "%par%" == "" goto :EOF
)

下の記述では、( )の中はひとまとまりのコマンドとみなされるため、 ifコマンドの%par%はどちらも ( ) の実行前の値(つまり"")で置き換えられているため、setコマンドで変数parを設定しても ifコマンドの判定は常に "" == "" となってしまい処理を終了します。
( )やFORコマンドの内での変数の変更とIFコマンドの判定には特に注意が必要です。
この問題に対処するには、ア.遅延環境変数を有効にする方法とイ.CALLコマンドを使う方法があります。

ア.遅延環境変数を使う方法
遅延環境変数とは、コマンドが実行される時点で変数を展開する動作のことです。
(SETコマンドの説明を参照)
遅延環境変数を使うには、コマンドプロンプトの起動時に /V オプションをつけるか、バッチファイル中で SETLOCAL ENABLEDELAYEDEXPANSION を宣言します。
使い方は、実行時に展開したい変数を % の代わりに ! で挟みます。
上の例では以下のように ( ) 内の IFコマンドを変更します。
SETLOCAL ENABLEDELAYEDEXPANSION → SETLOCALで遅延環境変数を設定
set par=
if "%par%" == "" (
set /p par=引数を設定してください:
if "!par!" == "" goto :EOF
)
ENDLOCAL → SETLOCAL設定の解除

イ.CALLコマンドによる修正
最初のifで ( ) による処理のブロック化を行わず、処理をサブルーチン化してCALLで呼び出します。
set par=
if "%par%" == "" CALL :set_par
if err EQU 1 goto :EOF
 ・
 ・
:set_par
set /p par=引数を設定してください:
if "%par%" == "" set /a err=1 else set /a err=0
exit /b

●CALLコマンドによる変数展開(再掲)
CALLコマンドによる環境変数の展開例
set p=%~dp0
if exist %~1 (
   set p=%~dp1
   call echo %%p%%
)
CALLコマンドは、通常、サブルーチンを呼び出すために使われますが、(if、forなどのバッチコマンド以外の)コマンドの呼び出しにも利用できます。
ここでは「call echo %%p%%」とすることで環境変数「p」の評価・展開が2回行われ、ifブロック内での変更後の値が表示されることになります。

●数値計算時の注意
数値計算を行うときは、表示の桁数を合わせるために
set n=7
set /a x=%n%+100
set x=%x:~-2%
のように0を付加する処理をよく行います。
ところが、普通は10進数として扱われる数字ですが、先頭が0で始まっている場合は、「8進数」と解釈されてしまいます。
「010」は10進数で「8」、「014」は10進数で「12」と解釈されますし、「08」や「09」などは8進数では使えない数字「8」「9」が含まれるのでエラーとなります。
桁揃えを行うのは表示の直前に行い、計算用の変数と表示用の変数を分けたほうがいいと思います。
また、setコマンドの説明にもありますが、「0x41」のように数字を「0x」で始めると16進数として扱われます。
さらに、バッチ処理では数値を2進数32桁(32bit)で2の補数形式を使って計算するようになっているのですが、コマンドプロンプトにはオーバーフローという概念が無いらしく、計算の結果が2進数32桁を超えても32桁内で計算をし続けようとします。
(例)
set /a x=2147483647+1 → -2147483648
set /a x=1073741824*2 → -2147483648
set /a x=-2147483648*2 → 0
などとなります。
10億を超える計算をするときは、計算の途中経過にも注意が必要です。

2進数とは、0 と 1 の2つの数字で数を表す方法です。→「ゼロから学ぶ2進数」(ITpro)
2の補数形式とは、2進数の桁数を固定(ここでは16桁:16bitとします。)し、(0000000000000000)2を基準(「0」とします。)としてここから1を引いた値(1111111111111111)2[=17桁目から桁借りをしたと考えます。]を-1と定める表現形式をいいます。
または、1を足すと(00000000000000000000)2=0となる数(1111111111111111)2=-1と考えてもかまいません。[桁上がりした17桁目の1は無視します。]
このため、正の数の上限を(0111111111111111)2=65535、負の数の下限を(1000000000000000)2=-65536と定め、最上位の桁(MSB)を符号ビット[0:正の数または零、1:負の数]として扱います。

コマンド引数(%0~%9)でファイル属性(アトリビュート:%~a番号)や参照時刻(タイムスタンプ:%~t番号)、ファイルサイズ(%~z番号)を利用するときは、ファイル名に「"」が含まれないように(例:"httpd.log"など)注意が必要です。


環境変数に改行文字を入れる方法

ECHO で複数行(改行を含めて)表示をさせたいときは、改行文字だけの環境変数を作っておくと便利です。

SETLOCAL ENABLEDELAYEDEXPANSION
rem (改行)は3つ続けます。
rem (^でエスケープされた最初の改行が2つ目の改行でLFに保存され、3つ目の改行でSETコマンドが終わります。)
SET LF=^(改行)
(改行)
(改行)
SET str=文字列!LF!次の文字列
ECHO !str!
ENDLOCAL
rem 環境変数の遅延展開を使うのがポイントです。

参考文献

http://otnx.jp/CMD/FrontPage/
http://www.ne.jp/asahi/hishidama/home/tech/windows/bat.html

ページトップへ戻る

サンプルプログラム

バッチコマンドでの日付/時間処理
時間計算
 指定された時刻と経過時間(秒数)から時刻を求めます。
 経過時間には負の数も使えます。また、日をまたぐ場合は、環境変数 dd に日数を格納します。
@rem-----------
@title 時間計算
@echo off
set hms=%~1
if "%hms%" == "" set /p hms=24時間形式(hh 00~23)で時刻を入力してください。(hh:mm:ss):
if "%hms%" == "" set hms=%TIME:~0,8%
for /f "tokens=1-3 delims=:" %%D in ("%hms%") do set /a hou=%%D&set /a min=%%E&set /a sec=%%F
set /a ps = hou * 3600 + min * 60 + sec
echo 00:00:00からの通算秒数:%ps%[s]
pause
set ts=%~2
if "%ts%" == "" set /p ts=経過秒数を入力してください。:
if "%ts%" == "" set /p ts=0
set /a ps += ts
if %ps% GEQ 0 set /a dd=ps / 86400
if %ps% LSS 0 set /a dd=ps / 86400 - 1
set /a ps -= dd * 86400
set /a hh = ps / 3600
set /a ps -= hh * 3600
set /a mm = ps / 60
set /a ps -= mm * 60
set /a ss = ps
echo 求める時間は %dd%日%hh%時%mm%分%ss%秒 です。
pause
echo on
@exit/b
@rem --------------------ここまで

日付の計算
 指定された日付と経過日数から日付を求めます。
 経過日数は負の数も使えます。
@rem --------------------ここから
@TITLE 日付計算(1)
@echo off
set dt=%~1
if "%dt%" == "" set /p dt=日付を入力してください。(yyyy/mm/dd):
if "%dt%" == "" set dt=%date%
set dt=%dt:~-10%
echo date=%dt%
for /f "tokens=1-3 delims=/" %%D in ("%dt%") do set y=%%D&set m=%%E&set d=%%F
rem 月数と日数の頭の0(01,02..08,09の0)を外す処理
set m=10%m%
set /a m = m - (m / 100) * 100
set d=10%d%
set /a d = d - (d / 100) * 100
set /a pd = (y - 1) * 365 + (y - 1) / 4 - (y - 1) / 100 + (y - 1) / 400
call :set_md
rem CALLコマンドの環境変数の展開が2段階であることを利用して配列風の使い方をしています。
rem CALLで呼び出されたコマンドは文法チェックを行われ、この段階で1度目の変数展開が行われます。
rem 次に、呼び出されたコマンドの実行段階で、再度変数の展開が行われます。
rem 結果、m = 4 の場合、文法チェックの段階で、call set /a od = %md[4]% と展開され、
rem さらに実行段階で、set /a od = 90 に展開されます。
call set /a od = %%md[%m%]%%
set /a od += d
set /a u = 0
if %m% GTR 2 call :uruu
set /a td = pd + od + u
echo 西暦1年1月1日(月)からの通算日数:%td%[日]

set days=%~2
if "%days%" == "" set /p days=%dt%からの経過日数:
if "%days%" == "" set /p days=0
set /a td += days
rem 365.2425 * 400 = 146097; 閏年を考慮した西暦年数への換算数
rem (td * 400 - 1) の -1 は400年に1度、146097(365.2425)で割り切れる日数になるのでこれを回避しています。
set /a y = (td * 400 - 1) / 146097
set /a yd = td - (y * 146097) / 400
set /a y += 1
set /a u = 0
call :get_m
set /a d = yd
rem 0で桁を揃えるためのダミー計算です。
set /a y = 10000 + y
set /a m = 100 + m
set /a d = 100 + d
call :set_wkday
set /a weekday = td - (td / 7) * 7
call set w=%%wd[%weekday%]%%
rem %y:~1,4% で2桁目から4桁分の文字列を取り出しています。
echo 求める日付:%y:~1,4%/%m:~1,2%/%d:~1,2% [%w%]
pause
@echo on
@exit/b

rem -----ここからサブルーチン
rem 年が閏年かどうかを判定し、年初からの日数(yd)をもとに月(m)と日(yd)を計算します。
rem 閏年の場合、無条件に yd から閏日の1日を引いておき、月が1月、2月であった場合に閏日を1日戻し入れしています。
:get_m
    call :uruu
    if %u% EQU 1 set /a yd -= 1
    if %yd% GTR 334 set /a yd = yd - 334&set /a m = 12&goto :EOF
    if %yd% GTR 304 set /a yd = yd - 304&set /a m = 11&goto :EOF
    if %yd% GTR 273 set /a yd = yd - 273&set /a m = 10&goto :EOF
    if %yd% GTR 243 set /a yd = yd - 243&set /a m = 9&goto :EOF
    if %yd% GTR 212 set /a yd = yd - 212&set /a m = 8&goto :EOF
    if %yd% GTR 181 set /a yd = yd - 181&set /a m = 7&goto :EOF
    if %yd% GTR 151 set /a yd = yd - 151&set /a m = 6&goto :EOF
    if %yd% GTR 120 set /a yd = yd - 120&set /a m = 5&goto :EOF
    if %yd% GTR 90 set /a yd = yd - 90&set /a m = 4&goto :EOF
    if %yd% GTR 59 set /a yd = yd - 59&set /a m = 3&goto :EOF
    if %yd% GTR 31 set /a yd = yd - 31 + u&set /a m=2&goto :EOF
    set /a yd += u&set /a m = 1
goto :EOF

rem 与えられた年が閏年かどうかを検査します。閏年なら u = 1 、閏年でなければ u = 0 です。
:uruu
    call :remainder %y% 400
    if %remainder% EQU 0 set /a u = 1&goto :EOF
    call :remainder %y% 100
    if %remainder% EQU 0 set /a u = 0&goto :EOF
    call :remainder %y% 4
    if %remainder% EQU 0 set /a u = 1&goto :EOF
    set /a u = 0
goto:EOF

rem 年数を400, 100, 4 で割ったときの余りを求めるサブルーチン
:remainder
    set /a remainder = %1 - (%1 / %2) * %2
exit /b %remainder%

rem 年の初めから各月の初めまでに経過している日数
:set_md
    set /a md[1] = 0
    set /a md[2] = 31
    set /a md[3] = 59
    set /a md[4] = 90
    set /a md[5] = 120
    set /a md[6] = 151
    set /a md[7] = 181
    set /a md[8] = 212
    set /a md[9] = 243
    set /a md[10] = 273
    set /a md[11] = 304
    set /a md[12] = 334
exit /b

rem 曜日を設定します。
:set_wkday
    set wd[0]=日
    set wd[1]=月
    set wd[2]=火
    set wd[3]=水
    set wd[4]=木
    set wd[5]=金
    set wd[6]=土
exit /b
rem ---------------------ここまで

ページトップへ戻る

ファイルの拡張検索
 指定のディレクトリーや拡張子のテキストファイルの内容を検索し、一致するデータを含む行、またはファイル名を表示します。
 検索ワードに一致するデータを含む行またはファイル名の一覧をファイルに出力することもできます。
@rem --------------------ここから
@TITLE 拡張検索
@echo off
REM 検索用パラメータを入力します。
SET /P d=検索ディレクトリー:

REM 検索先のディレクトリーが指定されなかった場合は使い方の表示を行います。
IF "%d%" == "" GOTO comments

SET /P s=検索キーワード:
SET /P o=オプション(/S /M 出力ファイル名):

REM オプション(/M:ファイル名の表示,/S:サブディレクトリの検索など)の文字列を分割します。
FOR /F "tokens=1-3*" %%O IN ("%o%") DO CALL :set_par %%O %%P %%Q %%R

REM 検索文字列を「"」で括ります。(もともと「"」が使われていた場合は、元の「"」を削除します。)
SET wk=%s:"=%
SET s="%s%"
IF "%wk:~0,3%" == "/C:" SET s=/C:"%wk:~3%"
IF "%wk:~0,3%" == "/c:" SET s=/C:"%wk:~3%"

REM 検索文字列が指定されていなかった場合は、空白行でないすべての行に一致させます。
IF %s% == "" SET s="."
echo 検索語:%s%

REM ディレクトリーコマンドからファイル名を受け取り、検索処理に引渡します。
FOR /F "usebackq tokens=*" %%F IN (`dir /B /A-D %m0% %d%`) DO (
    REM DOS標準の外部コマンドで検索を行います。
    findstr /R /P %m1% %m2% %s% "%%F" %m3%
)
pause
echo on
@exit /b

:set_par
    REM 検索用のパラメーターを整理し設定します。
    REM m0:/Sスイッチが指定されたときに「SET m0=/S」が設定されます。
    REM m1、m2:/Mスイッチが指定されたときにm1またはm2に「/M」が設定されます。
    REM m3:「/」でない文字から始まった場合、検索結果の出力用ファイル名と解釈されます。
    REM m4:予備の引数です。
    SET m0=
    SET m1=%~1
    SET m2=%~2
    SET m3=%~3
    SET m4=%~4
   
    REM sub*の処理で引数の順序を変更します。
    IF NOT "%m1:~0,1%" == "/" GOTO sub1
    IF NOT "%m2:~0,1%" == "/" GOTO sub2
    IF NOT "%m3:~0,1%" == "/" GOTO sub3
    IF NOT "%m4:~0,1%" == "/" GOTO sub4
        set m1=%~1
        set m2=%~2
        set m3=%~3
        set m4=%~4
    :ret1
   
    REM m1またはm2に/Sが設定されていたら、m0に設定を変更します。
    IF "%m1%" == "/S" SET m0=/S & SET m1=
    IF "%m1%" == "/s" SET m0=/S & SET m1=
    IF "%m2%" == "/S" SET m0=/S & SET m2=
    IF "%m2%" == "/s" SET m0=/S & SET m2=
   
    REM m1に/Mが設定されていたら、m2を空に変更します。
    IF "%m1%" == "/M" SET m2=
    IF "%m1%" == "/m" SET m2=
   
    REM m2に/Mが設定されていたら、m1を空に変更します。
    IF "%m2%" == "/M" SET m1=
    IF "%m2%" == "/m" SET m1=
   
    REM m3が半角/全角のスペースで始まっている場合、m3を空にします。
    IF "%m3:~0,1%" == " " SET m3=
    IF "%m3:~0,1%" == " " SET m3=
exit /b

:sub1
    REM 引数の1番目と3番目を入れ替えます。
    set m1=%~3
    set m2=%~2
    set m3=%~1
    set m4=%~4
GOTO ret1
:sub2
    REM 引数の2番目と3番目を入れ替えます。
    set m1=%~1
    set m2=%~3
    set m3=%~2
    set m4=%~4
GOTO ret1
:sub3
    REM 入れ替えはありません。
    set m1=%~1
    set m2=%~2
    set m3=%~3
    set m4=%~4
GOTO ret1
:sub4
    REM 引数の4番目と3番目を入れ替えます。
    set m1=%~1
    set m2=%~2
    set m3=%~4
    set m4=%~3
GOTO ret1

:comments
echo 検索対象のディレクトリーおよびサブディレクトリーにある(テキスト)ファイル
echo を検索キーワードで検索しキーワードに一致する行やファイル名を表示します。
echo (使い方) %~nx0
echo  検索ディレクトリー、検索キーワード、(検索)オプションを順次入力します。
echo  検索ディレクトリーを入力しなかった場合は、説明画面(この画面)が表示され
echo  ます。
echo  検索ディレクトリーは、絶対パスまたは相対パスで指定します。
echo   . → 現在のディレクトリー、
echo   .. → 1つ上位の(親)ディレクトリー
echo  検索キーワードには、正規表現が使えます。
echo   . → 任意の1文字
echo   [文字リスト] → 文字リストに含まれている1文字
echo   [^^文字リスト] → 文字リストに含まれていない文字
echo   [a-z] → 範囲で指定された文字リスト
echo   [a-zA-Z0-9_] 英数字と「_」
echo   [^^a-zA-Z] 英字でない文字(数字、記号、スペースなど)
echo   \\ → \記号
echo   \^^ → ^^記号
echo   \$ → $記号
echo   ^^ → 行頭
echo   $ → 行末
pause
echo  検索キーワードの例
echo   "使い方" → 「使い方」という文字列を指定します。
echo   "使い方 方法"→「使い方」または「方法」という文字列を指定します。
echo   [sS]et → 「set」または「Set」という文字列を指定します。
echo   <script.*type= → 「<script(任意の文字列)type=」を指定します。
echo   /C:"input type"「input type」という文字列を指定します。
echo    なお、半角英字の大文字、小文字は区別されます。
echo  オプション
echo   /M → キーワードに一致するデータを含むファイルの名前だけを表示します。
echo   /S → サブディレクトリーも含めて検索します。
echo   出力ファイル → 検索結果を出力ファイルに書き出します。
pause
echo on
@exit /b
@rem --------------------ここまで

自己消去処理(自殺処理)
 自分で自分自身のファイルを削除(自殺)する処理です。
 ファイルの最後に DEL コマンドを入れておけばいいのですが、ここではスクリプトを使ってDEL コマンドを追加しています。
@rem --------------------ここから
@title 自己消去(自殺処理) @echo off
set fn=%0
rem ここで、ファイルの最後に DEL コマンドを追加します。
echo del %fn% >>%fn%
pause
echo on
@rem --------------------ここまで

この例のようにBAT処理は、自分自身を含めてファイルの書き換えができるので、誤ったファイル名を指定してしまうと重要なファイルを破壊する可能性があるので十分に注意する必要があります。

【おまけ】
バッチ処理で自己増大:サイズ肥大化(自己増殖ではありません)する変態バッチ処理を書いてみます。
以下の処理を「autogrow.bat」などのファイル名で保存したあと実行します。

@rem ここから
@title 自己増大(ファイルサイズを増やす処理)@echo off
pushd %~dp0
rem バッチファイルの名前を取り出します。
set f=%~nx0
call :next
popd
pause
exit /b

rem -----------------------------------------ここからサブルーチン
:fwrite
if %~z1 GTR 1000 (
rem 引数 %1(=%f% =%0) のファイルサイズが1000byteを超えると処理を終了します。
echo rem >> %f%
echo goto :EOF >> %f%
) else (
rem サブルーチンの呼び出し処理を自分自身に追加モードで書き出します。
echo rem >> %f%
echo call :fwrite %f% >> %f%
)
exit /b

rem .........................................
:next
rem ファイルサイズを肥大化させる処理を呼び出します。
call :fwrite %f%
rem この後にサブルーチンの呼び出しが追加されていきます。

ファイルサイズ:732byte程度だったものが1022byte程度に増加します。
if条件と書き出しデータを工夫すれば(rem の後や call :fwrite %f% 以降の引数は自由に書き込めるので)、自己増大型の巨大テキストファイルが作れます。
サブルーチンファイルを使えばcopyで自己増殖させることもできそうです。
Windowsのバッチコマンドは単純ですが、工夫するとさまざまな処理を自動化することができます。


ページトップへ戻る

バッチサンプルのリスト

バッチサンプルの使い方
 バッチサブルーチンの使い方、バッチ処理の作り方
バッチサンプル1
 文字列の操作と10進数2進数変換、16進数変換など
バッチサンプル2-多桁計算
 加算(足し算)、減算(引き算)、乗算(掛け算)、除算(割り算)
バッチサンプル3-浮動小数点演算
 加算(足し算)、減算(引き算)、乗算(掛け算)、除算(割り算)
バッチサンプル4-IEを使ったGUI
 IEの画面入力をバッチに送ります。
バッチサンプル5-いろいろな処理パターン
 文字列の分割と抽出、Windowsのバージョンチェック、ファイル属性のチェック、IPアドレスの一覧など
バッチで使うVBscript
 バッチファイルからVBscriputを呼び出す方法とサンプルスクリプト。
 1.文字列の長さを求める
 2.対象文字列内から検索文字列の位置を求める
 3.対象文字列の指定位置から指定文字数を取り出します。
 4.正規表現を使って対象文字列を検索/置換します。
 5.メッセージボックスを表示してクリックされたボタンの値を返します。
 6.入力ボックスを表示して、入力された文字列を返します。
 7.指定の時間(ミリ秒単位)、処理を停止します。(sleep処理)
 8.レジストリから「マイ ドキュメント」のフォルダーを読み取りフォルダーごとコピーします。
 9.VBScriptの戻り値を配列で受け取る
 10.VBScriptからバッチファイルを呼びだすには
   指定ディレクトリ以下のサブディレクトリも含めてファイルを検索します。



ページトップへ戻る


【ページ内見出し】
◆ページトップ
◆バッチコマンドについて
◆SETコマンド
◆改行しないで文字列を表示
◆コマンド引数、環境変数の編集
◆ECHO で改行だけをさせるには
◆リダイレクトとパイプ
◆IFコマンドの構文
◆コマンドのブロック化
◆CALLコマンド
◆and,or 複合条件の判定
◆FORコマンドは、いろいろな使い方ができます。
◆PUSHDとPOPD
◆バッチ処理がうまく動かないとき
◆環境変数に改行文字を入れる方法
◆参考文献
◆サンプルプログラム
◆時間計算
◆日付の計算
◆ファイルの拡張検索
◆自己消去処理(自殺処理)
◆自己増大処理(肥大化処理)
◆バッチサンプルのリスト

【サイト内リンク】
■xcopyバックアップ
■バッチサンプルの使い方
■バッチサンプル(その1)
■バッチサンプル(その2)
■バッチサンプル(その3)
■バッチサンプル(その4)
■バッチサンプル(その5)
■バッチサンプル(その6)
■バッチで使うVBscript
■サイトトップページ


-広告エリア-







元のページに戻る  ページを閉じる

連絡先:お問い合わせフォーム