Fujitsuグループ@nifty

2009年7月10日金曜日

WINDOWS BATCH 処理

※バッチ処理の注意点
・copyコマンドのように「上書きしますか?(Y/N)」のリプライ応答を禁止して、強制的に上書きしないと
 リプライ応答の要求もしないで、次のステップに進んで行き、実際は上書きされていないので
 おかしな処理結果になってしまう。
 このためには、Replyの禁止をコマンド毎に依存するOptionで定義しなければならない。

>copy -y a.txt b.txt b.txtが存在しても上書きしますか?と尋ねられない。

記述 種類
内部/
外部
コマンド 書式 用例 説明
; 内部 ; ; バッチファイル内に空行を入れる
: 内部 :ラベル :END GOTOのジャンプ先として記述する。
CALL 内部 CALL [ドライブ名:][ディレクトリ名]
 ファイル名 [引数] CALL DELBAK.BAT
   ・・・・DELBAK.BATを呼び出す 現在のバッチファイルから他のバッチコマンドを呼び出す。
呼び出されたバッチコマンドが終了すると、
再び呼び出したバッチコマンドの続きが実行される。
CHOICE 外部
choice.com CHOICE [/C:選択文字列] [/T:文字,秒]
 [/N] [/S] [文字列]
 /C:選択文字を設定する
 /N:プロンプトの最後に?を表示しない
 /T:「秒」で指定した時間が経過したときに
  自動的に「文字」で指定されたキーが
押されたことにする
 /S:入力された文字の大文字と
  小文字を区別する CHOICE /C:ABC
   ・・・・AかBかCキーの入力を求める このコマンドは外部コマンドだが、バッチコマンドのためにある。
文字を選択させたいときに使用する。
たとえば「CHOICE /C:ABC 入力してください」
と記述したときには、画面に、
   入力してください[A,B,C]?
と表示される。ここでキーを押すと、次のように、
その文字の順番がエラーレベルとして設定される。
エラーレベルはIF文で判断して処理する。
   Aのキーが押された  →  ERRORLEVELは1に設定
   Bのキーが押された  →  ERRORLEVELは2に設定
   Cのキーが押された  →  ERRORLEVELは3に設定
/Cの指定がなかったときには「CHOICE /C:YN」を指定したことになる。
ECHO 内部 [@]ECHO [メッセージ|ON|OFF]
ECHO
 ・・・・ECHOと.の間にスペースは入れない ECHO
 ・・・・コマンドエコーの状態を表示する
ECHO OFF
 ・・・・以降のコマンドエコーをオフにする
ECHO これはメッセージです
 ・・・・メッセージを出力する
@ECHO
 ・・・・このコマンド自体を出力しない
ECHO. ・・・・改行のみ出力 ON/OFFを指定したときには、コマンドエコーの制御をする。
コマンドエコーをオフににすると、以後プロンプトやコマンド
そのものが表示されなくなる。
メッセージを指定したときにはそれを出力する。
たとえば、バッチコマンドの実行で、コマンドの説明文を
表示したいときなどに使う。
メッセージ内に改行を含めることはできないので、
複数行のメッセージを出力したいときには、ECHOコマンドを
複数記述する。ECHOという文字を出したくないときには、
先頭に@をつける。また、ただ改行したいだけ
のときには、ECHO.とする。
FINDRAMD 外部 FINDRAMD FINDRAMD RAMDRIVE.SYSで作成したRAMディスクをドライブ番号を得る。
起動ディスクに含まれている。
FOR 内部 FOR %変数 IN (セット) DO コマンド FOR %A IN (*.TXT) DO TYPE %A
 ・・・・*.TXTファイルを連続表示する
 FOR %A IN (A B) DO TYPE %A.TXT
  ・・・・テキストファイルA、BとTYPEする 「(セット)」で指定されているファイル名や文字の数だけ、
コマンドを操り返し実行する。その際、「(セット)」で
検索したファイル名や文字が%変数に格納されるので、
それをコマンドで利用することができる。
%変数は%A~%Zまで何を指定してもよい。ただし、
バッチファイル内に記述するときには、
%変数を、%%変数の形式に書き換える必要がある(例:%A→%%A)
GOTO 内部 GOTOラベル GOTO END ラベルのある行にジャンプする。
ラベルは「:END」のように記述する。
IF 内部 IF [NOT] ERRORLEVEL [=] 番号 コマンド
IF [NOT] 文字列1==文字列2 コマンド
IF [NOT] EXIST [ドライブ名:][ディレクトリ名]
 ファイル名 コマンド IF ERRORLEVEL 1 GOTO YES
 ・・・・エラーレベルが1ならばYESに進む
IF "%1"=="/N" DIR
 ・・・・1つ目の引数が/NならばDIRを実行
IF EXIST *.BAK DEL *.BAK
 ・・・・*.BAKファイルがあれば削除する 条件を判断して、「条件通りならば」その後に記述されている
コマンドを実行する。条件の前にNOTを付けると、
「条件通りでなければ」という判断になる。
ERRORLEVELの判断をするときには、あらかじめ
CHOICEコマンドを実行して、エラーレベルを設定しておく。
複数のエラーレベルを判断するときには、番号の
大きいほうから記述すること。なお、ERRORLEVELと番号の
間には「=」を入れても入れなくてもよい。
文字列の判断で「"%1"==""」とすれば、コマンド入力の際に
引数が指定されたか、されなかったかが判断できる。
LFNFOR 内部 LFNFOR [ON|OFF] LFNFOR ON FORコマンドを実行したとき、あらかじめ「LFNFOR ON」を
実行しておくと、長いファイル名を正しく表示することができる。
PAUSE 内部 PAUSE PAUSE バッチファイルの処理を一時停止する。そして、
「続けるにはどれかキーを押してください...」という
メッセージを表示する。何かキーを押すと次に進む。
REM 内部 REM [コマンド] REM これはコメントです バッチファイルファイル内にコメントを記述する。
REMに続くテキストは、コマンド実行において無視される。
実行させたくないコマンドの行頭にREMを挿入し、一時的に
無効にするといった使い方も可能である。
SHIFT 内部 SHIFT SHIFT バッチ変数%1、%2、%3・・・・の内容を1つずつ小さい
バッチ変数に移動する。これにより、%1には%2の内容が、
%2には%3の内容が入る。


■for文の使用例
・コマンドラインで使用する時(変数は、%変数)


>for %a in (*.gif) do dir %a
・バッチ処理に組み込んだ時(変数は、%%変数)


for %%a in (*.gif) do dir %%a
◇NT以降における機能拡張
FOR [スイッチ [オプション]] %%変数 IN (セット) DO コマンド [コマンドのパラメーター]
/D:指定したセットがワイルドカードを含む場合に、それがディレクトリ名であることを指示。
/R [[ドライブ:]パス] :サブディレクトリを再帰的に検索し、該当するすべてのディレクトリで
           FOR 文が実行される。
/L:セットが数値であることを宣言。
 この場合、セットは「開始値、ステップ、終了値」の形式で指定。たとえば、
 FOR /L %%I IN (101,1,200) DO ....
 と指定した場合、変数 %%I は101から始まって200まで1ずつ増えていく。
 FOR /L %%I IN (16,-1,0) DO ....
 と指定した場合、変数 %%I は16から始まって0まで1ずつ減っていく。
/F ["オプション"]:セットが(テキスト)ファイル名であることを指示。
 この場合のFORコマンドは、指定されたファイルの各行に対してコマンドを実行する。
例)


FOR /F %%I IN (ABC.TXT) DO ECHO %%I & PAUSE
※読み取られた各行の内容は、区切り文字(既定では半角スペース)によって分離されて、変数に格納される。
 たとえば、読み取ったABC.TXTの1行めが次の内容であった場合、%%I には WELCOME が格納される。
 WELCOME TO FPCU
 また、残りの2単語(トークン)は、暗黙に宣言された(とみなされる)下記の2つの変数に格納される。
 %%J …… TO
 %%K …… FPCU
※変数名が%%Jと%%Kなのは、もとのFORコマンドでユーザーが宣言した変数名が %%I だから。


FOR /F %%A IN (ABC.TXT) DO ECHO %%I
 ……のように、宣言された変数が%%Aであれば、2単語めは%%B、3単語めは%%Cに格納される。
※「テキストファイルの最初のn行を飛ばし読みしたい」
「CSV形式のファイルを処理するため、語の区切り文字を" "ではなく","にしたい」
 などなど、細かい活用のためのオプションも提供されている。
◇変数参照方法の拡張
「%%変数」からは、次の拡張書式で必要な情報を抽出できる。


%%~A 引用句 (") があればそれを削除する
%%~fA 完全修飾パス名を得る
%%~dA ドライブ文字を得る
%%~pA パス名だけを得る
%%~nA ファイル名だけを得る
%%~xA 拡張子だけを得る
%%~sA 短い名前を得る
%%~aA ファイルの属性を得る
%%~tA ファイルのタイムスタンプを得る
%%~zA ファイルサイズを得る
%%~$ENV:A 任意の環境変数名ENVに指定されているディレクトリを検索し、最初に見つかった
完全修飾名を得る。
その環境変数が未定義の場合、または検索してもファイルが見つからなかった
合は空の文字列が返る。

■startコマンド
現在のコマンド・プロンプトとは別に新しいプロセス(ウィンドウ)を開き、指定されたプログラムや
コマンドを実行する。
Taskの二重起動が許されている場合などに使用できる。


[バッチファイルの内容]
start test1.exe
start test2.exe
※同時に2つの窓が開く。
[バッチファイルの内容]
strat /w test1.exe
start /w test2.exe
※窓は1つしか開かないが、最初のコマンド終了後、Enterを押してやらないと次のコマンドが実行できない。~
■リダイレクトの使いかた


(1)標準出力をファイルへ出力 (新規ファイル作成)
【構文】 command > filename
【例】dir > out.txt
(2)標準出力をファイルへ出力 (ファイルへ追記)
【構文】 command >> filename
【例】dir >> out.txt
(3)エラー出力をファイルへ
【構文】 command 2> filename
【例】dir nonexist.txt 2>stderr.txt
(注)"2"と">"の間にスペースを追加してしまうと、"2"がコマンドのパラメータと解釈されてしまう。
(4)標準出力とエラー出力をファイルへ
【構文】 command > filename 2>&1
【例】dir nonexist.txt > out.txt 2>&1
■連続処理でキー入力待ちになる。
[xxxx.bat]
test.exe test1.txt
test.exe test2.txt
...
test.exe testn.txt
上記のようなbatファイルを実行すると一行事項するたびにキー入力待ち(Enterで次行へ)になる。
→先頭行にecho off を入れてみるがダメ。
結局、行末に <null が必要だった。(標準入力をnullに設定)

[xxxx.bat]
test.exe test1.txt<null
test.exe test2.txt<null
...
test.exe testn.txt<null
■ファイルディスクリプタ番号とリダイレクト
・ファイルディスクリプタ番号
 プログラムがアクセスするファイルや、コンソール等のデバイスを仮想識別子。
 0から順番に整数の番号が割り当てられる。
 標準では、0が標準入力、1が標準出力、2が標準エラー出力に割り当てられ、事前に CONデバイス
 がオープンされている。
 3番以降は、プログラムがオープンするファイル等に割り当てられる。
・リダイレクトとパイプ
 記号 < によって入力のリダイレクト、> によって出力のリダイレクトが出来るが、
 それぞれ0番、1番のファイルディスクリプタが対象となる。
 他の番号のディスクリプタをリダイレクトする場合は、< > の直前に数字を書く。
 数字は0から9までで、10> と書いても、10はディスクリプタ番号とはみなされない。
 リダイレクト先は、ファイルやCONやNUL等のデバイスの他、他のディスクリプタと同じと言う指定が出来る。
 例えば、標準出力と標準エラー出力の両方を同じファイルにリダイレクトしたい時、

dir xxx >file 2>&1
 と書く(順序が重要)。
 また、標準出力は|によるパイプ機能で他のプログラムの標準入力に渡すことが出来る。
 標準エラー出力もパイプで渡したい場合は、

route 2>&1 | more
 のように標準エラー出力を標準出力と同じものにリダイレクトしてパイプする。
 1だけをファイルに書きたい場合、echo 1>fileでは、1がディスクリプタ番号と見なされるため駄目で、


echo ^1>file
 と、^ で 1 をクォートするか、

>file echo 1
 と書く必要がある。
・リダイレクトの記述位置
 リダイレクトは、コマンドのどこに書いても良いが、forやifのように構造を持った構文全体を
 リダイレクトするには、( ) で囲む。

■バッチの実行方法
・拡張子は.batにする。
・バッチの中から別のバッチを実行する。

[他のバッチへ移る.bat:]
echo "start"
test.bat
echo "ここへは戻って来ない!"
[制御を戻したい場合]
;CALL命令を使う。(戻り値を返すには、「exit /b」を使用する)
echo "start"
call test.bat
echo "戻ってきた" %ERRORLEVEL%
pause
;「exit /b」でなく「exit」で終了するバッチファイルを呼び出すと、exitが呼ばれた時点でコマンドプロンプトが終了してしまう。
;この場合はcmd /cを使ってバッチを呼び出してやると、「exit 戻り値」で設定した戻り値が取得できる。
[exitで終了するバッチを呼び出す.bat:]
echo "start"
cmd /c test.bat
echo "返ってきた♪" %ERRORLEVEL%
pause

■環境変数


変数 内容 UNIX相当
%ERRORLEVEL% 直前に実行されたコマンド(や関数)の戻り値 $?
%0 実行コマンド名 $0
%1 %2 … %9 実行時引数(個別) $1 $2 …
%* 全引数 $* $@

・変数のシフト
 shiftコマンドで、個別の引数が1つ左へずれる。UNIXのshiftに相当。
 すなわち、%0には%1の値が入り、%1には%2の値が入り…、%9には%10相当の値が入る。
 %0も変わってしまうのと、%*は変わらない点がUNIXと違う。
 %0を変えたくない場合はオプションを付けて「shift /1」とする。これで%1以降だけが変わるようになる。
・環境変数のセット


set 環境変数=〔値〕 ※〔値〕を省略すると、その環境変数を削除する。
set /a 環境変数= 式 ※式を計算した結果をセットする。
set /p 環境変数=〔プロンプト〕※プロンプトを表示してコンソールからの入力を促し、入力された値を環境変数にセットする。

■演算子


演算子 説明 例
== EQU NEQ 比較
LSS LEQ
GTR GEQ 大小比較
NOT 否定 if not "%1" == "" echo 引数があります
DEFINED 環境変数が存在するとき、真 if defined TMP echo 有る
EXIST ファイル(やディレクトリ)が存在するとき、真
ファイル名をダブルクォーテーションでくくる
ことも出来るが、末尾のスペースは無視される模様。 if exist zzz.txt echo 在る
ERRORLEVEL %ERRORLEVEL%が値以上 if errorlevel 1 echo エラー

・ANDやORに当たるものは無いので、複雑な演算は出来ない。
・両方の項が数字だけで構成されていれば、数値として比較される。
・それ以外は文字列として比較される。
 例えば「"1"」は数値ではない(ダブルクォーテーションは数字じゃない)ので、「1」とは異なる。
 また、「/i」オプションを付けると、大文字小文字を無視して比較する。

if /i %1 equ abc (echo 一致!) else (echo 不一致)

■日付の処理
DOS窓での確認

>echo %DATE%
2008/11/19 (XP )   ※1月や1日は01
水 2008/11/19 (2000) ※2000ではフォマットが違い 曜日が余分に入る。
>echo %date:/=% ※コロンで置換する(:a=b "a"を"b"に置換する。"/"を""に置換)
20081119 (XP )
水 20081119 (2000)
>echo %DATE:~-10%   ※最後から(-)10文字を取る。
2008/11/19 (XP )
2008/11/19 (2000)
>echo %TIME%
23:27:30.57 (XP,2000)  ※ 57/100秒
>echo %TIME:~0,5%
23:27 (XP,2000) ※ 時分のみ抽出(0文字目から5文字分取る)
>set mytime5=%TIME:~0,5% ※先頭から5文字抽出。
>set mytime4=%mytime5::=% ※":"の文字を削除して4文字にする。
>set HHMM=%mytime4: =0% ※1桁の時は、" "が入るので"0"に置換
>echo %HHMM% ※HHMMの4桁を出力
2327
バッチ処理での確認

@echo off
set tmpDate10=%date:~-10%
set YYYYMMDD=%tmpDate10:/=%
echo %YYYYMMDD% ==> 20081119

set tmpTime5=%time:~0,5%
set tmpTime4=%tmpTime5::=%
set HHMM=%tmpTime4: =0%
echo %HHMM% ==> 2306

echo %YYYYMMDD%%HHMM% ==> 200811192306
pause

■文字列の連結
「"」や「'」は不要(その文字も連結される)。
連結子は無し(続けて列記)。
変数は、%変数名% で連結する。


>echo 現在の時刻は、%date% %time% です。
現在の時刻は、木 2008/11/20 9:28:52.23 です。 (2000)
現在の時刻は、2008/11/20 9:28:52.23 です。   (XP )

0 件のコメント:

コメントを投稿