睡在批处理文件里

当编写一个批处理文件来自动化 Windows 框中的某些东西时,我需要将其执行暂停几秒钟(通常在测试/等待循环中,等待进程启动)。当时,我能找到的最好的解决方案是使用 ping (我不是开玩笑的)来达到预期的效果。我发现了一个更好的 给你,它描述了一个可调用的“ wait. bat”,实现如下:

@ping 127.0.0.1 -n 2 -w 1000 > nul
@ping 127.0.0.1 -n %1% -w 1000> nul

然后,您可以在自己的批处理文件中包含对 wait. bat 的调用,并传递睡眠时间。

显然,Windows 2003资源工具包提供了一个类似 Unix 的 sleep 命令 (终于!).与此同时,对于我们这些仍在使用 WindowsXP、 Windows2000或(可悲的) 视窗 NT的人来说,还有更好的方法吗?

我修改了 接受的答案中的 sleep.py脚本,如果命令行上没有传递参数,那么它默认为一秒:

import time, sys


time.sleep(float(sys.argv[1]) if len(sys.argv) > 1 else 1)
152243 次浏览

资源套一直包括这一点,至少从 Windows2000开始。

此外,Cygwin 包有一个 sleep-扑通进入您的 PATH,包括 cygwin.dll(或无论它被称为)和方法去!

SLEEP.exe包含在大多数资源套件中,例如可以安装在 WindowsXP 上的 WindowsServer2003资源工具包

Usage:  sleep      time-to-sleep-in-seconds
sleep [-m] time-to-sleep-in-milliseconds
sleep [-c] commited-memory ratio (1%-100%)

我也遇到过类似的问题,但我只是用了一个很短的 c + + 控制台应用来做同样的事情。只需运行 MySleep.exe 1000-可能比下载/安装整个资源工具包更容易。

#include <tchar.h>
#include <stdio.h>
#include "Windows.h"


int _tmain(int argc, _TCHAR* argv[])
{
if (argc == 2)
{
_tprintf(_T("Sleeping for %s ms\n"), argv[1]);
Sleep(_tstoi(argv[1]));
}
else
{
_tprintf(_T("Wrong number of arguments.\n"));
}
return 0;
}

正常的使用是好的,只要你想“等一等”。这是因为您依赖于底层的其他函数,比如您的网络工作以及127.0.0.1上没有任何应答这一事实。也许它不太可能失败,但也不是不可能... ..。

如果您想确保您正在等待指定的时间,那么应该使用 sleep功能(它的优点是不使用 CPU 电源或等待网络准备就绪)。

查找已经为睡眠创建的可执行文件是最方便的方法。只需将其放入 Windows 文件夹或标准路径的任何其他部分,它就总是可用的。

否则,如果您有一个编译环境,您可以很容易地自己创建一个。 Sleep函数在 kernel32.dll中是可用的,所以您只需要使用那个函数. : -) 对于 VB/VBA,在源代码的开头声明以下内容来声明一个 sleep 函数:

private Declare Sub Sleep Lib "kernel32" Alias "Sleep" (byval dwMilliseconds as Long)

对于 C # :

[DllImport("kernel32.dll")]
static extern void Sleep(uint dwMilliseconds);

您可以在 睡眠功能(MSDN)中找到更多关于此功能(自 Windows2000以来可用)的信息。

在标准 C 中,sleep()包含在标准库中,而在微软的 Visual Studio C 中,如果内存允许的话,该函数名为 Sleep()。这两个参数以秒为单位,而不是像前两个声明那样以毫秒为单位。

更新

从 WindowsVista 及以后都可以使用的 timeout命令应该是所使用的命令,正如对这个问题的另一个 回答所描述的那样。下面是一个 老了答案。

旧答案

如果您已经安装了 Python,或者不介意安装它(它还有其他用途:) ,只需创建以下 瞌睡虫脚本并将其添加到 PATH 中的某个位置:

import time, sys


time.sleep(float(sys.argv[1]))

它将允许亚秒的暂停(例如,1.5秒,0.1,等等) ,如果你有这样的需要。如果你想把它命名为 sleep而不是 sleep.py,那么你可以把 .PY扩展添加到你的 PATHEXT 环境变量。在 WindowsXP 上,你可以编辑它:

我的电脑→属性(菜单)→高级(标签)→环境变量(按钮)→系统变量(帧)

我一直在使用这个 C # 睡眠程序。如果 C # 是您首选的语言,那么对您来说可能更方便:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;


namespace sleep
{
class Program
{
static void Main(string[] args)
{
if (args.Length == 1)
{
double time = Double.Parse(args[0]);
Thread.Sleep((int)(time*1000));
}
else
{
Console.WriteLine("Usage: sleep <seconds>\nExample: sleep 10");
}
}
}
}

比 Python 解决方案更轻量级的是 Perl 一句话。

要想睡上7秒钟,可以把以下内容写进 BAT 脚本:

perl -e "sleep 7"

此解决方案只提供一秒钟的分辨率。

如果需要更高的分辨率,请使用 Time: : HiRes 模块。它提供的 usleep()睡眠 和以纳秒为单位睡眠的 nanosleep() (两个函数都只接受整数参数) 堆栈溢出问题 在 Perl 中我如何睡上一毫秒的进一步细节。

我已经使用 ActivePerl很多年了 安装。

你可以使用 ping:

ping 127.0.0.1 -n 11 -w 1000 >nul: 2>nul:

等10秒。

之所以必须使用11,是因为第一个 ping 会立即发出,而不是在一秒钟之后。这个数字应该总是比您想要等待的秒数多一秒。

请记住,-w的目的不是控制数据包发送的频率,而是确保在出现网络问题的情况下等待的时间不超过 更多。如果您使用的是 ping127.0.0.1,那么不太可能出现问题,因此这可能是没有实际意义的。

ping命令本身通常每秒发送一个数据包。Windows 文档中实际上没有记录这一点,但它似乎遵循与 Linux 版本相同的规则(其中记录了这一点)。

在服务器故障,一个类似的问题被问到和解决方案有:

choice /d y /t 5 > nul

您可以使用 Windows Cscript WSH层和这个 等等 Js JavaScript 文件:

if (WScript.Arguments.Count() == 1)
WScript.Sleep(WScript.Arguments(0)*1000);
else
WScript.Echo("Usage: cscript wait.js seconds");

把这个放到你想等的批处理文件里。

@ping 127.0.0.1 -n 11 -w 1000 > null

根据您的兼容性需求,可以使用 ping:

ping -n <numberofseconds+1> localhost >nul 2>&1

等待5秒钟,使用

ping -n 6 localhost >nul 2>&1

或在 Windows7或更高版本上使用 timeout:

timeout 6 >nul

从 WindowsVista 开始,就可以使用 timeout命令:

c:\> timeout /?


TIMEOUT [/T] timeout [/NOBREAK]


Description:
This utility accepts a timeout parameter to wait for the specified
time period (in seconds) or until any key is pressed. It also
accepts a parameter to ignore the key press.


Parameter List:
/T        timeout       Specifies the number of seconds to wait.
Valid range is -1 to 99999 seconds.


/NOBREAK                Ignore key presses and wait specified time.


/?                      Displays this help message.


NOTE: A timeout value of -1 means to wait indefinitely for a key press.


Examples:
TIMEOUT /?
TIMEOUT /T 10
TIMEOUT /T 300 /NOBREAK
TIMEOUT /T -1

注意: 它不适用于输入重定向——例如:

C:\>echo 1 | timeout /t 1 /nobreak
ERROR: Input redirection is not supported, exiting the process immediately.

这个给我留下了深刻的印象:

Http://www.computerhope.com/batch.htm#02

choice /n /c y /d y /t 5 > NUL

从技术上讲,您告诉 choice命令只接受 y。它默认为 y,在5秒内完成,不绘制提示符,并将它所说的任何内容转储到 NUL (就像 Linux 上的 null 终端一样)。

我不同意我在这里找到的答案。

我使用以下完全基于 WindowsXP 功能的方法来延迟批处理文件:

推迟 BAT:

@ECHO OFF
REM DELAY seconds


REM GET ENDING SECOND
FOR /F "TOKENS=1-3 DELIMS=:." %%A IN ("%TIME%") DO SET /A H=%%A, M=1%%B%%100, S=1%%C%%100, ENDING=(H*60+M)*60+S+%1


REM WAIT FOR SUCH A SECOND
:WAIT
FOR /F "TOKENS=1-3 DELIMS=:." %%A IN ("%TIME%") DO SET /A H=%%A, M=1%%B%%100, S=1%%C%%100, CURRENT=(H*60+M)*60+S
IF %CURRENT% LSS %ENDING% GOTO WAIT

您还可以在计算中插入日期,这样当延迟间隔超过午夜时,该方法也可以工作。

当我不能(或者不想)添加更多可执行文件或者安装任何其他软件时,我就是这样使用 ping方法的。

您应该连接一些不存在的东西,并使用 -w标志,这样它就会在这段时间之后失败,而不是连接那里的 (比如 localhost) -n次数的东西。这可以让你处理的时间少于一秒钟,我认为这是稍微更准确。

例如:。

(测试没有使用1.1.1.1)

ECHO Waiting 15 seconds


PING 1.1.1.1 -n 1 -w 15000 > NUL
or
PING -n 15 -w 1000 127.1 >NUL

或者命令行 Python,例如,持续6秒半:

python -c "import time;time.sleep(6.5)"

在记事本上写:

@echo off
set /a WAITTIME=%1+1
PING 127.0.0.1 -n %WAITTIME% > nul
goto:eof

现在在文件夹 C: WINDOWS System32中保存为 wait. bat, 然后,无论何时你想等待,使用:

CALL WAIT.bat <whole number of seconds without quotes>

我喜欢 Aacini 的回答。我添加到它处理的一天,也使它能够处理 几厘米(%TIME%输出 H:MM:SS.CC) :

:delay
SET DELAYINPUT=%1
SET /A DAYS=DELAYINPUT/8640000
SET /A DELAYINPUT=DELAYINPUT-(DAYS*864000)


::Get ending centisecond (10 milliseconds)
FOR /F "tokens=1-4 delims=:." %%A IN ("%TIME%") DO SET /A H=%%A, M=1%%B%%100, S=1%%C%%100, X=1%%D%%100, ENDING=((H*60+M)*60+S)*100+X+DELAYINPUT
SET /A DAYS=DAYS+ENDING/8640000
SET /A ENDING=ENDING-(DAYS*864000)


::Wait for such a centisecond
:delay_wait
FOR /F "tokens=1-4 delims=:." %%A IN ("%TIME%") DO SET /A H=%%A, M=1%%B%%100, S=1%%C%%100, X=1%%D%%100, CURRENT=((H*60+M)*60+S)*100+X
IF DEFINED LASTCURRENT IF %CURRENT% LSS %LASTCURRENT% SET /A DAYS=DAYS-1
SET LASTCURRENT=%CURRENT%
IF %CURRENT% LSS %ENDING% GOTO delay_wait
IF %DAYS% GTR 0 GOTO delay_wait
GOTO :EOF

如果系统上有 PowerShell,那么只需执行以下命令:

powershell -command "Start-Sleep -s 1"

编辑: 从 我的答案也差不多开始,人们提出了一个问题,在这个问题中,Powershell 启动所需的时间与您试图等待的时间相比是非常重要的。如果等待时间的准确性很重要(即不能接受额外的一两秒延迟) ,可以使用这种方法:

powershell -command "$sleepUntil = [DateTime]::Parse('%date% %time%').AddSeconds(5); $sleepDuration = $sleepUntil.Subtract((get-date)).TotalMilliseconds; start-sleep -m $sleepDuration"

这需要在发出 windows 命令时花费时间,而 powershell 脚本一直睡眠到发出这个命令之后的5秒钟。因此,只要 powershell 启动所需的时间比您的睡眠时间短,这种方法就可以工作(在我的机器上大约是600ms)。

你可以通过在标题栏中添加 PAUSE 消息来变得有趣:

@ECHO off
SET TITLETEXT=Sleep
TITLE %TITLETEXT%
CALL :sleep 5
GOTO :END
:: Function Section
:sleep ARG
ECHO Pausing...
FOR /l %%a in (%~1,-1,1) DO (TITLE Script %TITLETEXT% -- time left^
%%as&PING.exe -n 2 -w 1000 127.1>NUL)
EXIT /B 0
:: End of script
:END
pause
::this is EOF

在 WindowsVista 上,你可以使用 暂停睡觉命令,但是要在 WindowsXP 或 WindowsServer2003上使用它们,你需要使用 WindowsServer2003资源工具包命令。

这里 你对睡眠替代方案有了一个很好的概述(ping 方法是最流行的,因为它可以在每台 Windows 机器上运行) ,但是(至少)有一个没有提到(ab)使用 W32TM(Time Service)命令:

w32tm /stripchart /computer:localhost /period:1 /dataonly /samples:N  >nul 2>&1

在这里,您应该用要暂停的秒替换 N。而且,它可以在没有必要条件的情况下在每个 Windows 系统上运行。

Typeperf 也可用于:

typeperf "\System\Processor Queue Length" -si N -sc 1 >nul

使用 mshta 和 javascript (可以在一秒内进入睡眠状态) :

start "" /wait /min /realtime mshta "javascript:setTimeout(function(){close();},5000)"

这应该更加精确(对于等待不到一秒钟的情况)——自我编译可执行文件依赖于 .net:

@if (@X)==(@Y) @end /* JScript comment
@echo off
setlocal
::del %~n0.exe /q /f
::
:: For precision better call this like
:: call waitMS 500
:: in order to skip compilation in case there's already built .exe
:: as without pointed extension first the .exe will be called due to the ordering in PATEXT variable
::
::
for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d  /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do (
set "jsc=%%v"
)


if not exist "%~n0.exe" (
"%jsc%" /nologo /w:0 /out:"%~n0.exe" "%~dpsfnx0"
)




%~n0.exe %*


endlocal & exit /b %errorlevel%




*/




import System;
import System.Threading;


var arguments:String[] = Environment.GetCommandLineArgs();
function printHelp(){
Console.WriteLine(arguments[0]+" N");
Console.WriteLine(" N - milliseconds to wait");
Environment.Exit(0);
}


if(arguments.length<2){
printHelp();
}


try{
var wait:Int32=Int32.Parse(arguments[1]);
System.Threading.Thread.Sleep(wait);
}catch(err){
Console.WriteLine('Invalid Number passed');
Environment.Exit(1);
}

您还可以使用.vbs 文件执行特定的超时:

下面的代码创建了. vbs 文件:

echo WScript.sleep WScript.Arguments(0) >"%cd%\sleeper.vbs"

然后下面的代码打开. vbs 并指定等待多长时间:

start /WAIT "" "%cd%\sleeper.vbs" "1000"

在上面的代码中,“1000”是要发送到。以毫秒为单位的 vbs 文件,例如,1000ms = 1 s。你可以把这部分改成你想要的长度。

下面的代码删除。在您使用完 vbs 文件之后。把这个放在批处理文件的末尾:

del /f /q "%cd%\sleeper.vbs"

这是所有的代码,所以很容易复制:

echo WScript.sleep WScript.Arguments(0) >"%cd%\sleeper.vbs"
start /WAIT "" "%cd%\sleeper.vbs" "1000"
del /f /q "%cd%\sleeper.vbs"

这在 WindowsXPSP3和 Windows7上进行了测试,并使用了 CScript。我安装了一些安全保护装置,以避免“德尔”提示。(/q将是危险的)

等一下:

终止执行1000

等待500毫秒,然后运行后的东西:

sleepOrDelayExecution 500 dir \ /s

Bat:

@echo off
if "%1" == "" goto end
if NOT %1 GTR 0 goto end
setlocal
set sleepfn="%temp%\sleep%random%.vbs"
echo WScript.Sleep(%1) >%sleepfn%
if NOT %sleepfn% == "" if NOT EXIST %sleepfn% goto end
cscript %sleepfn% >nul
if NOT %sleepfn% == "" if EXIST %sleepfn% del %sleepfn%
for /f "usebackq tokens=1*" %%i in (`echo %*`) DO @ set params=%%j
%params%
:end

在 Windows2000之后的所有 Windows 版本中,最好的解决方案应该是:

timeout numbersofseconds /nobreak > nul

有一个更好的睡眠方式使用 ping。您将需要 ping 一个不存在的地址,因此可以以毫秒精度指定超时。幸运的是,这样的地址是在标准(RFC 3330)中定义的,它是 192.0.2.x。这不是虚构的,它实际上是一个地址,其唯一的目的就是不存在。需要说明的是,这甚至适用于本地网络。

192.0.2.0/24-此块被指定为“ TEST-NET”,用于 文档和示例代码 供应商和协议中的域名 example.com 或 example.net 块中的地址不应显示在 公共互联网。

要睡123毫秒,使用 ping 192.0.2.1 -n 1 -w 123 >nul

更新: 根据评论,还有 127.255.255.255

timeout /t <seconds> <options>

例如,要使脚本执行不可中断的2秒等待:

timeout /t 2 /nobreak >NUL

这意味着脚本将在继续之前等待2秒钟。

默认情况下,按键会中断超时,因此如果您不希望用户能够中断(取消)等待,请使用 /nobreak开关。此外,超时将提供每秒通知,通知用户还有多长时间可以等待; 这可以通过将命令通过管道传送到 NUL来删除。

编辑: 作为 @ martineau 在评论中指出timeout命令只能在 Windows 7及以上版本中使用。此外,与 timeout相比,ping命令使用的处理器时间更少。尽管如此,我仍然相信在可能的情况下使用 timeout,因为它比 ping‘ hack’更具可读性。阅读更多 给你

ping -n X 127.0.0.1 > nul

将 X 替换为秒数 + 1。

例如,如果您要等待10秒,将 X 替换为11。要等待5秒,使用6。

以毫秒为单位阅读前面的答案。

Pathping. exe 可以睡眠少于秒。

@echo off
setlocal EnableDelayedExpansion
echo !TIME! & pathping localhost -n -q 1 -p %~1 2>&1 > nul & echo !TIME!

.

> sleep 10
17:01:33,57
17:01:33,60


> sleep 20
17:03:56,54
17:03:56,58


> sleep 50
17:04:30,80
17:04:30,87


> sleep 100
17:07:06,12
17:07:06,25


> sleep 200
17:07:08,42
17:07:08,64


> sleep 500
17:07:11,05
17:07:11,57


> sleep 800
17:07:18,98
17:07:19,81


> sleep 1000
17:07:22,61
17:07:23,62


> sleep 1500
17:07:27,55
17:07:29,06

由于其他人建议使用第三方程序(Python、 Perl、自定义应用程序等) ,另一个选择是在 http://gnuwin32.sourceforge.net/packages/coreutils.htm上提供的 GNUCoreUtils for Windows。

部署的两种选择:

  1. 安装完整的包(包括完整的 CoreUtils 套件、依赖项、文档等)。
  2. 只安装“ sleep. exe”二进制文件和必要的依赖项(使用 depes.exe 获取依赖项)。

部署 CoreUtils 的一个好处是,您还可以获得许多其他有助于编写脚本的程序(Windows 批处理还有很多不足之处)。

只是为了好玩,如果您已经安装了 Node.js,您可以使用

node -e 'setTimeout(a => a, 5000)'

它可以在 Node v12.14.0的 Mac 上工作。

有很多方法可以在 cmd/batch 中完成“ 睡觉”:

我最喜欢的一个:

TIMEOUT /NOBREAK 5 >NUL 2>NUL

这将使控制台停止5秒钟,没有任何输出。

最常用的:

ping localhost -n 5 >NUL 2>NUL

这将尝试连接到 localhost5次。因为它是托管在您的计算机上,它将始终到达主机,所以每一秒钟,它将尝试新的每一秒钟。-n标志指示脚本将尝试连接的次数。在这种情况下是5,所以它将持续5秒钟。

最后一个的变体:

ping 1.1.1.1 -n 5 >nul

在这个脚本中,它与上一个脚本有一些不同之处。这不会尝试调用 localhost。相反,它将尝试连接到 1.1.1.1,一个非常快的网站。动作将持续5秒 只有当你有一个活跃的互联网连接。否则,它将持续约15完成的行动。我不推荐使用这种方法。

ping 127.0.0.1 -n 5 >nul

这与示例2(最常用的)完全相同。此外,您还可以使用:

ping [::1] -n 5 >nul

相反,它使用 IPv6的 localhost版本。

有许多方法可以执行此操作。但是,我更喜欢用于 WindowsVista 和更高版本的方法1,以及用于操作系统更早版本的最常用方法(方法2)。

使用 timeout

cmdpowershell中执行下一个命令之前,timeout 10将等待10秒钟

关于这个问题,有很多答案都提到了 ping 的使用,但大多数答案都指向环回地址或现在被视为 DNS 有效地址的地址。

相反,您应该使用一个仅供文档使用的 TEST-NET IP 地址,每个 IETF。
(更多相关信息请点击这里)

下面是一个完整注释的批处理脚本,演示了如何使用 ping 来使用睡眠函数:

@echo off
:: turns off command-echoing


echo/Script will now wait for 2.5 seconds & echo/
:: prints a line followed by a linebreak


call:sleep 2500
:: waits for two-and-a-half seconds (2500 milliseconds)


echo/Done! Press any key to continue ... & pause >NUL
:: prints a line and pauses


goto:EOF
:: prevents the batch file from executing functions beyond this point




::--FUNCTIONS--::


:SLEEP
:: call this function with the time to wait (in milliseconds)


ping 203.0.113.0 -n 1 -w "%~1" >NUL
:: 203.0.113.0 = TEST-NET-3 reserved IP; -n = ping count; -w = timeout


goto:EOF
:: ends the call subroutine

当然,你也可以直接使用这个命令,如果你不想做一个函数的话:
ping 203.0.113.0 -n 1 -w 时间以毫秒为单位 >NUL