←
▼
▲
エラー in C:\folderA\folderB\out.txt
C:\folderA がソースをインストールした任意のフォルダで、次のような出力結果が正しいとき、
out_ans.txt
そこで、out_ans.txt をバッチファイルで作成することで、インストールした状態が変わっても
自動的に判定することができるようになります。
C:\folderA の部分は、インストールした状態によって変わってしまいます。
つまり、単純なファイルの比較で、出力結果が正しいかどうかを自動的に判定することが
できません。
pushd ..\..
set base=%cd%
popd
set out=out_ans.txt
if exist %out% del %out%
echo エラー in %base%\folderB\out.txt>>%out%
echo.>>%out%
set out=
set base=
T_ALL_4_setup.bat
←ここを修正する
←ここで絶対パスを得る
絶対パスをすべて大文字にするとき
ツールによっては出力結果を勝手に大文字だけにするものがある。
これに対処するには、次のようにして、大文字だけが入った base_i 環境変数を使う。
cscript //nologo set_base_i.vbs > _set.bat & call _set.bat & del _set.bat
echo %base_i%\FILE.TXT
T_ALL_4_setup.bat
Set g_sh = WScript.CreateObject("WScript.Shell")
WScript.Echo "Set base_i="+ UCase( g_sh.CurrentDirectory )
set_base_i.vbs
Test.vbs
Sub test_setup( tests )
Dim base : base = g_sh.GetAbstructPathName( "..\.." )
Dim f : Set f = g_fs.CreateTextFile( "out_ans.txt", True, False )
f.WriteLine "エラー in " + base + "\folderB\out.txt"
f.WriteLine ""
Pass
End Sub
echo エラー in %base%\folderB\out.txt
echo.
out_ans.txt
..\..
out_ans.txt
"エラー in " + base + "\folderB\out.txt"
..\..
←
▼
▲
内部用と公開用、外部依存モジュールあり/なし、ソースパッケージとバイナリパッケージ、
のようにファイルの構成が大きく異なるときは、1つのフルパッケージから、それぞれの
パッケージを自動的に作成できるようにするとよいでしょう。
REM --- package name ---
set p=ModuleA
call :rmdir %p%
REM --- copy folder ---
call :copy ..\Modules_src\ModuleA %p%\ModuleA
if %r%==1 goto :eof
call :copy ..\Modules_src\ModuleB %p%\ModuleB
if %r%==1 goto :eof
modules_src
ModuleA
ModuleB
_pack
ModuleA_src
Modules_src
サンプル・パッケージの構成例
ModuleA_make.bat
Modules_make.bat
フルパッケージ
ModuleA のみのパッケージ
ModuleA と ModuleB を組み合わせたパッケージ
ModuleA_src フォルダを作成するバッチファイル
Modules_src フォルダを作成するバッチファイル
・ライブラリのソース、またはバイナリ
・ライブラリを使うアプリのサンプル
コンパイルエラーとリンクエラーをチェックするために、最低限下記のものが必要です。
この構成で、動作確認を行います。
rmdir, copy サブルーチンを使ったサンプル:
サンプル:
→ ver_pack.lzh
Modules_src
マスターファイル(コピー元)
ModuleA_patch
ModuleA をコピーした後に上書き修正するファイル
←
▼
▲
@echo off
if "%~1"=="" cmd /K %0 /wnd %1 %2 %3 %4
shift
pushd ..
REM base folder is vbslib_new
echo base folder is %cd%
echo OK?
pause
set src_name=vbs_inc.vbs
set src=TestByFCBat\vbs_inc\vbslib\%src_name%
for /R %%i in (%src_name%) do (
if exist "%%i" if not "%cd%\%src%"=="%%i" (
fc /A "%src%" "%%i"
if errorlevel 1 explorer /select, "%%i"&goto fin
)
)
:fin
echo.
echo done in %cd%
echo.
popd
set src_name=
set src=
比較&選択
echo %%i
xcopy /D "%src%" "%%i"
コピー
fc の行を変えます
src_name と src を、
マスターファイルの
パスにします
複数のフォルダにある同じ名前のファイルの内容を同じにします。
内容が異なると、マスターではない方のファイルを自動的に選択します。
←
▼
▲
do.bat
project_template
src
test
alltest
test1
alltest.bat
call_do.bat
do_each.bat
setting.bat
(a) メイン・バッチ
(d) 内部用(コール・バッチ)
(c) フォルダ一覧 (要修正)
(b) 環境変数設定 (要修正)
do.bat
(e) クリーン、ビルド、テストなどを実行 (要修正)
(e) クリーン、ビルド、テストなどを実行 (要修正)
alltest.bat
setting.bat
do_each.bat
call_do.bat
do.bat
(a) メイン・バッチ
(b) 環境変数設定 (要修正)
(c) フォルダ一覧 (要修正)
(d) 内部用(コール・バッチ)
(e) クリーン、ビルド、テストなどを実行 (要修正)
>auto
全フォルダのクリーン→リビルド→テストを実行します。
バッチファイルを起動するときは、カレントディレクトリに起動するバッチファイルが
ある状態で行ってください。
all
デフォルトの実行を表示して確認してから実行します。
>do build
1つのフォルダのリビルドを行います。
auto.bat と do.bat のパラメータに指定できるのは、次のとおりです。
(なし)
全フォルダのクリーン→ビルド→テスト→クリーンを実行します。
build
test
clean
リビルドを実行します。
テストを実行します。
クリーンを実行します。
全フォルダ(alltest.bat)、または1つのフォルダ(do.bat)に対して、ビルドやテストなどを行います。
テンプレート
if exist Build.dat del Build.dat
if exist Build.wrn del Build.wrn
if exist Build.err del Build.err
if exist Build.log del Build.log
set rmdir_path=obj
if exist %rmdir_path% rmdir /S /Q %rmdir_path%
if exist %rmdir_path% echo cannot delete %rmdir_path% & set r=1& goto :eof
set rmdir_path=
→ clean
PB delete
→ コマンドライン・コンパイル(VS2005)
→ batchlib.lzh
→ vbslib.lzh
vbslib 製テスト・プロンプトをお使いください。
←
▼
▲
echo ----- reset test folder -----
if exist test_do rmdir /S /Q test_do
mkdir test_do
xcopy /E /Y original test_do
echo cd .. & a.bat > a.bat
original フォルダ
テストを実行するバッチファイルの一部
リセット状態のファイル構成が入ったフォルダ
test_do フォルダ
リセットするテスト実施用フォルダ
test_do フォルダを一度削除し、originai フォルダの内容と一致させます(リセットします)。
clean.bat
for /D /R %%i in (test_do) do if exist "%%i" rmdir /S /Q "%%i"
テスト終了後に、すべての test_do フォルダを削除します
←
▼
▲
echo off
echo ----- setup tools -----
call ..\common\setting.bat
if (%test_prog%)==() echo not set %%test_prog%% & set r=1 & if (%no_pause%)==() pause & goto :eof
if not exist %test_prog% echo not found %test_prog% & set r=1 & if (%no_pause%)==() pause & goto :eof
set case=test1
echo ----- %case% -----
%test_prog% %case% > %case%_out.txt
%feq% %case%_out.txt %case%_ans.txt
if errorlevel 1 echo NG & set r=1 & if (%no_pause%)==() pause & goto :eof
set r=0 & echo Pass. if (%no_pause%)==() pause
REM ----- common setting -----
set test_prog="..\..\Debug\prog.exe"
プログラムのパスは、デバッグ版とリリース版、また、Program Files に入っていたりして、
変わることがよくあります。 そこで、各テストバッチファイルから、テストグループ共通の
setting.bat を呼び出すようにします。
setting.bat
clean.bat
del out1.txt
←
▼
▲
notepad.exe は、結果の表示に使うことができます。
if "%notepad%"=="" start "" notepad log.txt
if not "%notepad%"=="" start "" %notepad% log.txt
下記のバッチファイルは、notepad 環境変数が設定してあったら、別のプログラムで
log.txt を表示します。
me 設定
set notepad="C:\Program Files\sted\sted.exe"
←
▼
▲
all_test.bat
echo off
pushd test1
call test1.bat
popd
if not %r%==0 echo NG & set r=1 & goto :eof
set r=0 & echo Pass.
:eof2
if "%1"=="" pause
各テストのバッチファイルを呼び出し、テスト結果が入った環境変数をチェックします。
最後に表示される Pass か NG で全テストの結果を判定をします。
set errorlevel しても if errorlevel で判定できません。
←
▼
▲
.exe 形式の main 関数の返り値は、エラーレベルに格納されます。
if errorlevel 1 echo NG & set r=1 & goto :eof
1以上ならNG
if not errorlevel 1 echo NG & set r=1 & goto :eof
0 なら NG
echo %errorlevel% でエラーレベルの値が分かります。
errorlevel
)
、
エラーレベル
環境変数 r に代入していますが、これは、後述する全テスト実行バッチのためです。
set r=0 & echo Pass.
:eof2
if "%1"=="" pause
NG が無く、バッチファイルの最後まで来たら、次のように Pass したことを明示します。
参考
errorlevel 構文を使う
errorlevel 変数を使う
cscript sample.vbs
if not "%errorlevel%"=="21" echo ERROR & pause & goto :eof
Windows2000以降?
cmd /v:on /c "prog1 & echo exit /b !ERRORLEVEL! > _tmp.bat" | prog2
call _tmp.bat
echo %ERRORLEVEL%
パイプの前段のエラーレベルを知りたいとき
関連
→ 終了コード (Linux)
←
▼
▲
echo /* [DEBUGGING] */ a & pause & cls
実行中に止める
全体の動きを見る
・注目したい箇所に、特有のコメント、または、ファイルへリダイレクトする echo を入れます。
REM /* [DEBUGGING] */ a
・注目したい箇所に、変数に関するコメントを入れます
・echo on にするか、バッチファイル内で set echo_on=1 に対応させて、
実行ログをファイルに出力しながら、実行するバッチファイルを作成して実行します。
REM /* [DEBUGGING] */ r=%r%
echo on
set echo_on=1
( call auto.bat 2>&1 ) > log.txt
if "%notepad%"=="" start "" notepad log.txt
if not "%notepad%"=="" start "" %notepad% log.txt
set echo_on=
x.bat
auto.bat
2>&1 で、標準エラー出力も log.txt に出力しています。
>call
実行ログで、どのバッチファイルを実行しているかどうかは、call 文を検索すれば
分かります。
if not (%rr%)==(0) echo %cd%^>&echo /* [DEBUGGING] */ %msg%&pause
→ x.lzh
and の使い方が誤っています。
上記は、次の命令に対するエラーです。
→ x_me.lzh
または、
del "C:\batlog.txt"
echo /* [DEBUGGING] */ a >> "C:\batlog.txt"
←
▼
▲
set prog="%ProgramFiles%\prog\prog.exe"
if not exist %prog% echo %prog% が見つかりません & echo exit. & pause & goto :eof
%prog% %1
プログラムを呼び出すときは、次のようにバッチファイルの先頭で、プログラムの存在をチェック
するようにしてください。
バッチファイルにパラメータが必要なときは、次のようにチェックします。
%1 ではなく %~1 にしているのは、"" が付いていたらカットするためです。
if "%~1"=="" echo 使い方: %bat_name% (folder) & echo exit. & pause & goto :eof
パラメータに指定したパスを、プログラムに渡すときは、"%1" のようにしないでください。
"" で囲んだパスは %1="c:\file.txt" になります。
%prog% %1
%*
すべてのパラメータ
←
▼
▲
NUL リダイレクト
dir > nul
何も表示しません
環境変数を設定するバッチファイルの出力
echo set /A a=1 > setting.bat
call setting.bat
echo (%a%)
/A をつけないと、a="1" ではなく、a="1 " になってしまいます。
2>&1
で、標準エラー出力を、標準出力します。
( call bad.bat 2>&1 ) > log.txt
サンプル
標準入力の自動化
echo F | xcopy a.txt b.txt
xcopy a.txt b.txt < input.txt
xcopy に F と入力する
xcopy に input.txt の内容を入力
dir 2> nul
エラー出力は表示しません
( call bad.bat 2>&1 ) | tee log.txt
標準出力しながら、ファイルに出力する
( call bad.bat 2>&1 ) | safetee -o log.txt
command 2> err.txt
で、標準エラー出力をリダイレクトします。
→ safetee コマンド
子プロセスを起動するプログラムのリダイレクトの注意
それぞれのプロセスが printf する内容をファイルにリダイレクトした場合、
それぞれのプロセスごとに出力内容が集まります。 おそらく、バッファ
リングされているためと思われます。
process A 1
process B 1
process A 2
process B 2
リダイレクトしない場合
リダイレクトする場合
process A 1
process A 2
process B 1
process B 2
←
▼
▲
>call /?
バッチ プログラムを別のバッチ プログラムから呼び出します。
CALL [ドライブ:][パス]ファイル名 [バッチパラメータ]
バッチパラメータ バッチ プログラムで必要なコマンド ライン情報を指定します。
コマンド拡張機能を有効にすると、CALL は次のように変更されます:
CALL コマンドは、CALL のターゲットとしてラベルを受け付けるようになります。
構文は、次のとおりです:
CALL :ラベル 引数
指定された引数で新しいバッチ ファイル コンテキストが作成され、指定
されたラベルの次の文に制御が渡されます。バッチ スクリプト ファイルの
最後に 2 回到達することによって、2 回 "終了" する必要があります。
1 回目に最後に到達したときには、制御は CALL 文の次の行に返されます。
2 回目に、バッチ スクリプトが終了します。バッチ スクリプトから "戻る"
ための GOTO :EOF 拡張機能の説明については、GOTO /? と入力してください。
また、バッチ スクリプトの引数参照 (%0、%1 など) の展開は、次のように
変更されました:
%* バッチ スクリプト内では、すべての引数 (%1、%2、%3、%4、
%5 など) を参照します。
バッチ パラメータ (%n) の置換は拡張されました。次のオプション構文
を使うことができます:
%~1 - すべての引用句 (") を削除して、
%1 を展開します。
%~f1 - %1 を完全修飾パス名に展開します。
%~d1 - %1 をドライブ文字だけに展開します。
%~p1 - %1 をパスだけに展開します。
%~n1 - %1 をファイル名だけに展開します。
%~x1 - %1 をファイル拡張子だけに展開します。
%~s1 - 展開されたパスは、短い名前だけを含みます。
%~a1 - %1 をファイル属性に展開します。
%~t1 - %1 をファイルの日付/時刻に展開します。
%~z1 - %1 をファイルのサイズに展開します。
%~$PATH:1 - PATH 環境変数に指定されているディレクトリを
検索し、最初に見つかった完全修飾名に %1 を
展開します。環境変数名が定義されていない場合、
または検索してもファイルが見つからなかった
場合は、この修飾子を指定すると空の文字列に
展開されます。
修飾子を組み合わせて、複合結果を得ることもできます:
%~dp1 - %1 をドライブ文字とパスだけに展開します。
%~nx1 - %1 をファイル名と拡張子だけに展開します。
%~dp$PATH:1 - PATH 環境変数に指定されているディレクトリを
検索して %1 を探し、最初に見つかったファイル
のドライブ文字とパスだけに展開します。
%~ftza1 - %1 を DIR の出力行のように展開します。
上の例の %1 と PATH は、ほかの有効な値で置き換えることができ
ます。%~ 構文は有効な引数の数によって区切られます。%~ 修飾子
は %* と同時には使用できません。
call 先で設定した環境変数は、戻ってきても引き継がれます。
goto :eof
call 元へ戻ります。
call 先で設定された環境変数は、 call に続いて & で同じ行に書いた次の命令では
反映されていません。 call の次の行で反映されます。
set rr=0
call sub.bat & echo (%r%)
echo (%r%)
:sub_ret
set r=%rr%
goto ret
main.bat
sub.bat
set r=1
出力
(0)
(1)
第1引数を処理名にすると、同じファイルの中で call することができます。
@echo off
set _this=%0
if "%1"=="" goto _main
if "%1"=="_sub" shift & goto _sub
echo ERROR! invalid param1 of %_this% & pause & goto ret
:_main
echo _main
call %_this% _sub 1
pause
goto :ret
:_sub
echo _sub %1
goto :ret
:ret
set _this=
出力
_main
_sub 1
→ バッチファイル・テンプレート
コマンドプロンプトで入力したバッチファイル名になります。
>sample
sample
>..\sample.bat
..\sample.bat
バッチファイルをダブルクリックしたら、"" で囲まれたフルパスになります。
"C:\dir\file.bat"
>sample.bat "a b"
%1="a b"
%~1=a b
call a.bat
call :label param1 ...
同じバッチファイルの中をコール。 %1 などは置き換わります
call 元へ戻ります。 (すぐにバッチファイルを終了する方法は不明。)
goto :eof
型チェックが無いので、ライブラリの引数の構成が変わると、移植が大変になります。
たとえば a_ で始まる環境変数を、パラメータ用にするとよいでしょう。
set a_paramX=
set a_Y=
リターンする直前や、初期化時に、a_ で始まる環境変数はリセットしてください。
goto ret
:ret
REM ^>call_return %0
別ファイルコール
同ファイルコール
call :label ... > log.txt とすると、サブルーチンの出力をすべてリダイレクトします。