20

スクリプトの完了にかかった時間を計算するスクリプトを作成するにはどうすればよいですか?

こうなるだろうと思っていたのですが、明らかに違います..

@echo off
set starttime=%time%
set endtime=%time%

REM do stuff here

set /a runtime=%endtime%-%starttime%
echo Script took %runtime% to complete
4

6 に答える 6

40

元のバッチ ファイルについて 2 つのことが飛び出します。しかし、どちらも長期的には役に立ちません。

  1. ベンチマーク方法が何であれ、操作前の開始時刻と操作の終了時刻を必ず取得してください。あなたのサンプルはそれをしません。

  2. %time%「12:34:56.78」のようなものに評価され、SET /Aコマンドはそれらを減算できません。単純なスカラー タイム スタンプを生成するコマンドが必要です。

私はそれができないと言おうとしましたが、バッチ言語は信用されているよりもはるかに強力であるため、TIMER.BAT の簡単な実装を次に示します。記録のために、Pax は、私がいじっている間に文字列が分割されていることを示す回答で私を打ち負かし、Johannes Rössel は演算を測定領域の外に移動することを提案しました。

@echo off
setlocal

rem Remeber start time. Note that we don't look at the date, so this
rem calculation won't work right if the program run spans local midnight.
set t0=%time: =0%

rem do something here.... but probably with more care about quoting.
rem specifically, odd things will happen if any arguments contain 
rem precent signs or carets and there may be no way to prevent it.
%*

rem Capture the end time before doing anything else
set t=%time: =0%

rem make t0 into a scaler in 100ths of a second, being careful not 
rem to let SET/A misinterpret 08 and 09 as octal
set /a h=1%t0:~0,2%-100
set /a m=1%t0:~3,2%-100
set /a s=1%t0:~6,2%-100
set /a c=1%t0:~9,2%-100
set /a starttime = %h% * 360000 + %m% * 6000 + 100 * %s% + %c%

rem make t into a scaler in 100ths of a second
set /a h=1%t:~0,2%-100
set /a m=1%t:~3,2%-100
set /a s=1%t:~6,2%-100
set /a c=1%t:~9,2%-100
set /a endtime = %h% * 360000 + %m% * 6000 + 100 * %s% + %c%

rem runtime in 100ths is now just end - start
set /a runtime = %endtime% - %starttime%
set runtime = %s%.%c%

echo Started at %t0%
echo Ran for %runtime%0 ms

100 分の 1 秒の部分を気にしないことで、算術演算を単純化し、この全体的な精度についてもう少し正直にすることができます。これは、sleep コマンドまたはその他の時間浪費があると仮定した場合の動作です。

C:> TIMER SLEEP 3
Script took 3000 ms to complete
C:> 

編集:コメントで提案されているように、コードとその説明を修正しました。

NT チームが COMMAND.COM を CMD.EXE に置き換えたとき、大きく異なるものにすることはできないと考えたのだと思います。しかし実際には、それはほぼ完全に新しい言語です。拡張機能が有効になっている場合、古いお気に入りのコマンドの多くに新しい機能が追加されます。

それらの 1 つはSETLOCAL、変数が呼び出し元の環境を変更するのを防ぐことです。もう1つはSET /A、驚くべき量の算術演算を提供するものです。ここで使用した主なトリックは、新しい部分文字列抽出構文です。%t:~3,2%これは、 という名前の変数の値のオフセット 3 から始まる 2 文字を意味しますt

本当にショッキングなことに、set の完全な説明を見てください (SET /?プロンプトで試してみてください)。それでも怖くない場合はFOR /?、ファイルからテキストを解析できることに注意してください...

編集 2:コメントに Frankie によって含まれている08か報告された時間フィールドの誤った処理を修正しました。09いくつかのことを微調整し、いくつかのコメントを追加しました。

ここには明らかな見落としがあることに注意してください。おそらく修正するつもりはありません。コマンドの開始日と終了日が異なる場合は機能しません。つまり、時刻に関連する計算を行い、違いを報告しますが、その違いはあまり意味がありません。

少なくともこのケースについて警告するように修正するのは簡単です。正しいことを行うように修正するのはより困難です。

編集 3: %h% が 1 桁の時間に正しく設定されていないエラーを修正しました。これは、%time% が「9:01:23.45」を返すためです。スペースに注意してください。%time: =0% を使用すると、スペースが先行ゼロに置き換えられ、%h% が正しく設定されます。このエラーは、スクリプトが 1 桁の時間から次の時間にかけて実行された場合にのみ発生しました。

于 2009-04-11T06:41:45.493 に答える
4

これは一種の接線ですが、役立つ場合があります。

Microsoft には、多かれ少なかれ unix 'time' コマンドの拡張バージョンのように機能する timeit.exe プログラムがあります。それはWindows Server 2003 Resource Kitに含まれており、あなたが提案しているようなことをしたいと思っていたときはほとんど置き換えられました。

一見の価値があるかもしれません。

于 2009-04-11T06:28:40.673 に答える
3

優れた小さなルーチン。ただし、計算が 2 日間にわたる場合、計算は正しくありません。結果は、24 時間 (8640000 センチ秒) から減算する必要があります。

また、関連する行で重複している「set」コマンドの 1 つを削除します。

地域の設定は TIME 関数の形式に影響することに注意してください。英国では小数点はコンマではなくピリオドです。

台詞

日の間の時間を測定したかもしれません。

if %ENDTIME% LSS %STARTTIME% set set /A DURATION=%STARTTIME%-%ENDTIME%

に変更する必要があります

何日にもわたって時間を測定したかもしれません

if %ENDTIME% LSS %STARTTIME% set /A DURATION=8640000 - (%STARTTIME% - %ENDTIME%)
于 2012-10-31T13:37:47.780 に答える
2

地域設定に依存しないように、WMI を介して時刻を取得するこのスクリプトを確認してください。

@echo off
::::::::::::::::::::::::::::::::::::::::::
::  TimeDiff v1.00 by LEVENTE ROG       ::
::       www.thesysadminhimself.com     ::
::::::::::::::::::::::::::::::::::::::::::
 
::[ EULA ]:::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::  Feel free to use this script. The code can be redistributed  ::
::  and edited, but please keep the credits.                     ::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 
::[ CHANGELOG ]::::::::::::::
::  v1.00 - First Version  ::
:::::::::::::::::::::::::::::
 
 
FOR /F "skip=1 tokens=1-6" %%A IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Second /Format:table ^| findstr /r "."') DO (
 set Milisecond=%time:~9,2% 
 set Day=%%A
 set Hour=%%B
 set Minute=%%C
 set Second=%%D
)
set /a Start=%Day%*8640000+%Hour%*360000+%Minute%*6000+%Second%*100+%Milisecond%
 
::
::
:: PUT COMMANDS HERE
ping www.thesysadminhimself.com
::
::
 
FOR /F "skip=1 tokens=1-6" %%A IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Second /Format:table ^| findstr /r "."') DO (
 set Day=%%A
 set Hour=%%B
 set Minute=%%C
 set Second=%%D
)
set Milisecond=%time:~9,2% 
set /a End=%Day%*8640000+%Hour%*360000+%Minute%*6000+%Second%*100+%Milisecond%
set /a Diff=%End%-%Start%
set /a DiffMS=%Diff%%%100
set /a Diff=(%Diff%-%DiffMS%)/100
set /a DiffSec=%Diff%%%60
set /a Diff=(%Diff%-%Diff%%%60)/60
set /a DiffMin=%Diff%%%60
set /a Diff=(%Diff%-%Diff%%%60)/60
set /a DiffHrs=%Diff%
 
:: format with leading zeroes
if %DiffMS% LSS 10 set DiffMS=0%DiffMS!%
if %DiffSec% LSS 10 set DiffMS=0%DiffSec%
if %DiffMin% LSS 10 set DiffMS=0%DiffMin%
if %DiffHrs% LSS 10 set DiffMS=0%DiffHrs%
 
echo %DiffHrs%:%DiffMin%:%DiffSec%.%DiffMS%
于 2011-03-11T17:31:03.910 に答える
2

私の個人的な好みは、Cygwin をインストールしてtimeコマンドを使用することですが、実際にバッチファイルとして実行する必要がある場合は、文字列を単に減算するだけではなく、部分として扱う必要があります。

次のスクリプトは、10 秒の ping コマンドの時間を計り、負の数に縛られることなく 1 日の境界を越えることができます。わずかな強化により、多くの日の境界を越えることができます。

@echo off
setlocal enableextensions enabledelayedexpansion
set starttime=%time%
ping -n 11 127.0.0.1 >nul: 2>nul:
set endtime=%time%

set /a hrs=%endtime:~0,2%
set /a hrs=%hrs%-%starttime:~0,2%

set /a mins=%endtime:~3,2%
set /a mins=%mins%-%starttime:~3,2%

set /a secs=%endtime:~6,2%
set /a secs=%secs%-%starttime:~6,2%

if %secs% lss 0 (
    set /a secs=!secs!+60
    set /a mins=!mins!-1
)
if %mins% lss 0 (
    set /a mins=!mins!+60
    set /a hrs=!hrs!-1
)
if %hrs% lss 0 (
    set /a hrs=!hrs!+24
)
set /a tot=%secs%+%mins%*60+%hrs%*3600

echo End     = %endtime%
echo Start   = %starttime%
echo Hours   = %hrs%
echo Minutes = %mins%
echo Seconds = %secs%
echo Total   = %tot%

endlocal
于 2009-04-11T06:24:39.950 に答える
1

バッチ スクリプトで時間演算を直接行うことはできないため、時間差を計算する外部プログラムが必要になるか、時間の各部分を抽出してその方法で演算を行う必要があります。

後者の方法の例については、このフォーラム スレッドの下部を参照してください。ここに抜粋:

@エコーオフ
cls
レム=============================================== = ======
REM = 日時フォーマットの設定 =
レム=============================================== = ======
DT=%DATE% %TIME% に設定
年を設定=%DT:~10,4%
set mth=%DT:~4,2%
設定日=%DT:~7,2%
set hour=%DT:~15,2%
min=%DT:~18,2% に設定
set sec=%DT:~21,2%
set newDT=%year%_%mth%_%date% %hour%%min%%sec%

時間 = 14 に設定
最小値を 10 に設定

レム ===============================
REM = 取得終了時刻 =
レム ===============================
EndTime=%TIME% に設定
設定 EndHour=%EndTime:~0,2%
EndMin=%EndTime:~3,2% に設定


レム ===============================
REM = 違いを見つける =
レム ===============================
set /a Hour_Diff=EndHour - 時間 >nul
/a Min_Diff=EndMin を設定 - min >nul


レム ===============================
REM = 時針の変化? =
レム ===============================
IF [%Hour_Diff]==[0] (

期間を設定=%Min_Diff%
) そうしないと (

/a Duration=60-%Min_Diff% >nul を設定します
)


エコー開始時間 = %hour% : %min%
エコー終了時間 = %EndHour% : %EndMin%
エコー。
echo Min Diff = %Min_Diff%
エコー。
エコー時間差 (分) = %Duration%

また、タイプミスだと思いますが、処理endtime 後に必ず設定してください。

于 2009-04-11T06:21:25.090 に答える