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

关于原始批处理文件有两件事情发生。但从长远来看,两者都无济于事。

  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

您可以通过不打扰第二部分的百分之一来简化算术并对其整体准确性更加诚实。假设你有一个 sleep 命令或其他一些浪费时间的命令,它就在这里起作用:

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

编辑:我按照评论中的建议修改了代码及其描述。

我认为,当 NT 团队将 COMMAND.COM 替换为 CMD.EXE 时,他们认为他们无法让它变得非常不同。但实际上,它几乎是一种全新的语言。如果启用了扩展,许多常用的常用命令都有新功能。

其中之一是SETLOCAL防止变量修改调用者的环境。另一个是SET /A给你大量的算术。我在这里使用的主要技巧是新的子字符串提取语法,这%t:~3,2%意味着在名为的变量的值中从偏移量 3 开始的两个字符t

对于真正令人震惊的事情,请查看 set 的完整描述(尝试SET /?提示),如果这不会吓到您,请查看FOR /?并注意它可以解析文件中的文本......

编辑 2:修复了对 Frankie 在评论中包含0809报告的时间字段的错误处理。调整了一些东西,并添加了一些评论。

请注意,这里有一个明显的疏忽,我可能不会修复。如果命令的开始日期与结束日期不同,它将不起作用。也就是说,它会做一些与一天中的时间相关的数学运算并报告差异,但差异并不意味着什么。

修复它以至少警告这种情况很容易。修复它以做正确的事情更难。

编辑 3:修复了 %h% 未正确设置单位数小时的错误。这是由于 %time% 返回“9:01:23.45”。注意空间。使用 %time: =0% 将空格替换为前导零,并且将正确设置 %h%。仅当脚本从一位数小时运行到下一小时时,才会发生此错误。

于 2009-04-11T06:41:45.493 回答
4

这有点切线,但它可能会帮助你。

Microsoft 有一个 timeit.exe 程序,其工作方式或多或少类似于 unix 'time' 命令的增强版本。它出现在Windows Server 2003 Resource Kit中,并且几乎取代了我一直想做的事情,就像你建议的那样。

可能值得一看。

于 2009-04-11T06:28:40.673 回答
3

优秀的小程序。但是,如果计算跨越两天,则计算不正确。结果需要从 24 小时(8640000 厘秒)中减去。

还要删除相关行中重复的“设置”命令之一。

请注意,区域设置会影响 TIME 函数的格式,小数点在英国是句号而不是逗号。

线条

rem,我们可能已经测量了几天之间的时间

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

需要更改为

rem,我们可能已经测量了几天的时间

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

我个人的偏好是安装 Cygwin 并使用该time命令,但是,如果您实际上必须将其作为批处理文件执行,则不能只减去字符串,您必须将它们视为部分。

以下脚本将为 10 秒的 ping 命令计时,该命令能够跨越一天的边界而不会被负数束缚。轻微的增强将允许它跨越许多天的界限。

@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 回答
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 回答
1

您不能直接在批处理脚本中进行时间算术,因此您需要一个外部程序来计算时间差,或者提取时间的每个部分并以这种方式进行算术。

查看此论坛主题的底部,了解如何执行后者的示例。摘录在这里:

@echo 关闭
分类
REM ================================================== = ======
REM = 设置日期时间格式 =
REM ================================================== = ======
设置 DT=%DATE% %TIME%
设置年份=%DT:~10,4%
设置第 mth=%DT:~4,2%
设置日期=%DT:~7,2%
设置小时=%DT:~15,2%
设置 min=%DT:~18,2%
设置秒=%DT:~21,2%
设置 newDT=%year%_%mth%_%date% %hour%%min%%sec%

设置小时=14
设置最小值=10

REM ================================
REM = 获得结束时间 =
REM ================================
设置结束时间=%TIME%
设置 EndHour=%EndTime:~0,2%
设置 EndMin=%EndTime:~3,2%


REM ================================
REM = 寻找差异 =
REM ================================
设置 /a Hour_Diff=EndHour - 小时 >nul
设置 /a Min_Diff=EndMin - min >nul


REM ================================
REM = 时针变化?=
REM ================================
IF [%Hour_Diff]==[0] (

设置持续时间=%Min_Diff%
) 别的 (

设置 /a 持续时间=60-%Min_Diff% >nul
)


echo 开始时间 = %hour% : %min%
回声结束时间 = %EndHour% : %EndMin%
回声。
回声最小差异 = %Min_Diff%
回声。
回波时间差(分钟)= %Duration%

我也认为这是一个错字,但您确实希望确保在处理endtime 进行设置。

于 2009-04-11T06:21:25.090 回答