批处理文件执行需要多长时间?

发布于 2024-07-17 02:10:52 字数 223 浏览 7 评论 0原文

如何编写脚本来计算脚本完成所需的时间?

我以为会是这样,但显然不是。

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

REM do stuff here

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

How can I write a script to calculate the time the script took to complete?

I thought this would be the case, but obviously not..

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

REM do stuff here

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

如此安好 2024-07-24 02:10:52

关于原始批处理文件,有两件事发生了。

  1. 无论您采用哪种基准测试方法,请务必捕获操作之前的开始时间和操作之后的结束时间。 您的示例不会这样做。

  2. %time% 的计算结果类似于“12:34:56.78”,而 SET /A 命令无法减去这些值。 您需要一个生成简单标量时间戳的命令。

我本来想说这是不可能完成的,但是批处理语言比它想象的要强大得多,所以这里是 TIMER.BAT 的一个简单实现。 根据记录,帕克斯(Pax)击败了我,在我摆弄时给出了显示字符串分裂的答案,约翰内斯·罗塞尔(Johannes Rössel)建议将算术移到测量区域之外:

@echo off
setlocal

rem Remember 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 percent 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

您可以简化算术并对整体精度更加诚实不去理会第二部分的百分之一。 这里它正在运行,假设您有睡眠命令或其他一些浪费时间的命令:

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

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

我认为,当 NT 团队用 CMD.EXE 替换 COMMAND.COM 时,他们认为他们无法摆脱使其变得如此不同的情况。 但实际上,它几乎是一种全新的语言。 如果启用扩展,许多常用的旧命令都会具有新功能。

其中之一是SETLOCAL,它可以防止变量修改调用者的环境。 另一个是SET /A,它为您提供了大量的算术运算。 我在这里使用的主要技巧是新的子字符串提取语法,其中 %t:~3,2% 表示名为 t< 的变量值中从偏移量 3 开始的两个字符/代码>。

如果您想真正感到震惊,请查看 set 的完整描述(在提示下尝试 SET /?),如果这没有吓到您,请查看 FOR /?并注意它可以解析文件中的文本...

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

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

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

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

Two things leap out about the original batch file.

  1. Whatever your benchmark method, be sure to capture the start time before the operation, and the end time after the operation. Your sample doesn't do that.

  2. %time% evaluates to something like "12:34:56.78", and the SET /A command can't subtract those. You need a command that produces a simple scalar time stamp.

I was going to say it can't be done, but the batch language is a lot more powerful than it is given credit for, so here is a simple implementation of TIMER.BAT. For the record, Pax beat me to an answer showing the string splitting while I was fiddling around, and Johannes Rössel suggested moving the arithmetic outside of the measured region:

@echo off
setlocal

rem Remember 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 percent 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

You could simplify the arithmetic and be a little more honest about the overall accuracy of this by not bothering with the 100ths of a second part. Here it is in action, assuming you have a sleep command or some other time waster:

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

Edit: I revised the code and its description as suggested in a comment.

I think that when the NT team replaced COMMAND.COM with CMD.EXE, they thought they wouldn't get away with making it very different. But in effect, it is almost an entirely new language. Many of the old favorite commands have new features if the extensions are enabled.

One of those is SETLOCAL which prevents variables from modifying the caller's environment. Another is SET /A which gives you a remarkable amount of arithmetic. The principle trick I've used here is the new substring extraction syntax where %t:~3,2% means the two characters starting at offset 3 in the value of the variable named t.

For a real shocker, take a look at the full description of set (try SET /? at a prompt) and if that doesn't scare you, look at FOR /? and notice that it can parse text out of files...

Edit 2: Fixed mishandling of time fields containing 08 or 09 reported by Frankie in comments. Tweaked a couple of things, and added some comments.

Note that there is a glaring oversight here that I'm probably not going to fix. It won't work if the command starts on a different day than it ends. That is, it will do some math related to the time of day and report a difference, but the difference won't mean much.

Fixing it to at least warn about this case is easy. Fixing it to do the right thing is harder.

Edit 3: Fixed error where the %h% is not set properly for single digit hours. This is due to %time% returning " 9:01:23.45". Notice the space. Using %time: =0% replaces the space with a leading zero and %h% will be set correctly. This error only occurred when a script ran from one single digit hour to the next.

牛↙奶布丁 2024-07-24 02:10:52

这有点离题,但它可能会对你有所帮助。

Microsoft 有一个 timeit.exe 程序,其工作方式或多或少类似于 unix“time”命令的增强版本。 它位于 Windows Server 2003 资源工具包,它几乎取代了我想做的事情(如您建议的那样)的所有时间。

也许值得一看。

This is kind of tangential, but it may help you out.

Microsoft has a timeit.exe program that works more or less like an enhanced version of the unix 'time' command. It comes in the Windows Server 2003 Resource Kit, and it has pretty much replaced all the times I've wanted to do something like what you're suggesting.

It may be worth a look.

笑红尘 2024-07-24 02:10:52

我个人的偏好是安装 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

My own personal preference is to install Cygwin and use the time command but, if you actually have to do it as a batch file, you can't just subtract the strings, you have to treat them as parts.

The following script will time a 10-second ping command with the ability to cross a single day boundary without getting tied up in negative numbers. A slight enhancement would allow it to cross many day boundaries.

@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
一紙繁鸢 2024-07-24 02:10:52

很棒的小例程。 但是,如果计算跨越两天,则计算不正确。
结果需要减去 24 小时(8640000 厘秒)。

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

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

线

我们可能测量了几天之间的时间的

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

rem需要更改为

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

if %ENDTIME% LSS %STARTTIME% set /A DURATION=8640000 - (%STARTTIME% - %ENDTIME%)

Excellent little routine. However, if the calculation spans across two days, the calculation is incorrect.
The result needs subtracting from 24 hours (8640000 centiseconds).

Also remove one of the duplicate 'set' commands in the relevant line.

Note that regional settings affect the format of the TIME function, the decimal being a fullstop in UK rather than a comma.

The lines

rem we might have measured the time inbetween days

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

need changing to

rem we might have measured the time across days

if %ENDTIME% LSS %STARTTIME% set /A DURATION=8640000 - (%STARTTIME% - %ENDTIME%)
安静被遗忘 2024-07-24 02:10:52

查看此脚本,它将通过 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%

Check out this script that will retrieve time through WMI so it's Regional Setting independent.

@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%
咽泪装欢 2024-07-24 02:10:52

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

看看这个的底部论坛主题了解如何执行后者的示例。 摘录如下:

@echo off
cls
REM ================================================== ======
REM = Setting Date Time Format =
REM ================================================== ======
set DT=%DATE% %TIME%
set year=%DT:~10,4%
set mth=%DT:~4,2%
set date=%DT:~7,2%
set hour=%DT:~15,2%
set min=%DT:~18,2%
set sec=%DT:~21,2%
set newDT=%year%_%mth%_%date% %hour%%min%%sec%

set hour=14
set min=10

REM ===============================
REM = Getting End Time =
REM ===============================
set EndTime=%TIME%
set EndHour=%EndTime:~0,2%
set EndMin=%EndTime:~3,2%


REM ===============================
REM = Finding Difference =
REM ===============================
set /a Hour_Diff=EndHour - hour >nul
set /a Min_Diff=EndMin - min >nul


REM ===============================
REM = Hour Hand Change? =
REM ===============================
IF [%Hour_Diff]==[0] (

Set Duration=%Min_Diff%
) ELSE (

Set /a Duration=60-%Min_Diff% >nul
)


echo Start Time = %hour% : %min%
echo End Time = %EndHour% : %EndMin%
echo.
echo Min Diff = %Min_Diff%
echo.
echo time difference (mins) = %Duration%

我也认为这是一个拼写错误,但您确实希望确保在处理后设置endtime

You can't do time arithmetic directly in batch scripting, so you'll either need an external program to calculate the time difference, or extract each part of the time and do arithmetic that way.

Take a look at the bottom of this forum thread for an example of how to do the latter. Excerpted here:

@echo off
cls
REM ================================================== ======
REM = Setting Date Time Format =
REM ================================================== ======
set DT=%DATE% %TIME%
set year=%DT:~10,4%
set mth=%DT:~4,2%
set date=%DT:~7,2%
set hour=%DT:~15,2%
set min=%DT:~18,2%
set sec=%DT:~21,2%
set newDT=%year%_%mth%_%date% %hour%%min%%sec%

set hour=14
set min=10

REM ===============================
REM = Getting End Time =
REM ===============================
set EndTime=%TIME%
set EndHour=%EndTime:~0,2%
set EndMin=%EndTime:~3,2%


REM ===============================
REM = Finding Difference =
REM ===============================
set /a Hour_Diff=EndHour - hour >nul
set /a Min_Diff=EndMin - min >nul


REM ===============================
REM = Hour Hand Change? =
REM ===============================
IF [%Hour_Diff]==[0] (

Set Duration=%Min_Diff%
) ELSE (

Set /a Duration=60-%Min_Diff% >nul
)


echo Start Time = %hour% : %min%
echo End Time = %EndHour% : %EndMin%
echo.
echo Min Diff = %Min_Diff%
echo.
echo time difference (mins) = %Duration%

I also assume it's a typo, but you do want to be sure to set endtime after processing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文