在批处理文件中休眠

165

当编写Windows批处理文件以自动化某些操作时,我需要暂停其执行几秒钟(通常在测试/等待循环中,等待进程启动)。当时,我能找到的最佳解决方案使用ping(我不是在开玩笑)来实现所需的效果。我发现了一个更好的写作方法here,其中描述了一个可调用的“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命令(终于有了!)。与此同时,对于那些仍在使用Windows XP、Windows 2000或(遗憾地)Windows NT的人来说,是否有更好的方法呢?

我修改了sleep.py脚本中被接受的答案,以便如果没有在命令行上传递任何参数,则默认为一秒钟:

import time, sys

time.sleep(float(sys.argv[1]) if len(sys.argv) > 1 else 1)

微软的下载页面显示Windows 2003资源工具包也适用于XP。 恐怕没有其他选择,只能使用“外部”实用程序来进行等待:XP命令处理器中没有类似的功能。 - GerG
请查看以下两个链接,了解如何在批处理文件中实现等待命令和睡眠命令: - Wael Dalloul
2
你有几个选项 - 使用 ping 命令模拟睡眠,或下载包含 sleep 命令的 Windows 资源工具包。更多详情请参见:批处理文件 SLEEP 命令 - Rudu
http://stackoverflow.com/questions/5437201/how-to-wait-in-a-batch-script/5822491 http://stackoverflow.com/questions/1304738/wait-in-console https://dev59.com/OG445IYBdhLWcg3wWI-L https://dev59.com/23VC5IYBdhLWcg3w2k-I - Chris Moschini
批处理文件停止各种技术的良好总结:https://www.robvanderwoude.com/wait.php - user1934286
显示剩余5条评论
34个回答

243

从Windows Vista开始,可以使用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.

9
不支持无控制台使用: "错误:不支持输入重定向,立即退出进程。" - simpleuser
我的意思是你根本没有控制台的情况,例如当批处理文件通过从某些其他进程fork,cygwin crontab或远程SSH命令在后台运行时。 - simpleuser
1
哦,我知道了。我给出的例子只是为了演示错误 :) - Blorgbeard
3
@Cristian Ciupitu添加的关于timeout命令的链接部分错误- Windows XP没有此命令。 - martineau
1
@HelloWorld,那似乎是你的%PATH%出了问题。 - Blorgbeard
显示剩余2条评论

20

当我不能(或不想)添加更多可执行文件或安装其他软件时,按照所述使用ping方法是我的做法。

你应该对不存在的东西进行ping,并使用-w标志以在该时间后失败,而不是对存在的东西(例如localhost)进行-n次ping。这允许您处理小于一秒钟的时间,而且我认为它略微更精确。

例如:

(测试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

立即返回 PING:传输失败。一般故障。 - huysentruitw
IP地址 1.1.1.1 已被CloudFlare占用,因此不需要等待15秒,而是只需等待几毫秒。 - hdev
这就是为什么你不要选择一些“肯定没有被占用”的IP地址 x) - mafu

19

更新

timeout 命令在 Windows Vista 及以后版本中可用,应该使用该命令,如另一个答案所述。下面是一个旧的答案。

旧的答案

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

import time, sys

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

如果你需要进行亚秒级的暂停(例如,1.5秒、0.1秒等),它将允许这样做。如果你想将它称作 sleep 而不是 sleep.py,那么你可以将 .PY 扩展名添加到你的 PATHEXT 环境变量中。在 Windows XP 上,你可以在以下位置进行编辑:

我的电脑 → 属性(菜单)→ 高级选项卡 → 环境变量(按钮)→ 系统变量(框)


33
当需要批处理的解决方案时,为什么要使用Python编写脚本?如何通过路径扩展来解决Windows用户没有安装Python解释器的问题? - Val
6
为了可移植性考虑,我认为应该避免使用此解决方案,因为存在完全合适的本地替代方案。 - Gras Double
1
这种方法在过去可能提供了一种解决方法,但是由@Blorgbeard描述的本地解决方案绝对是正确的选择。 - Mike

16

SLEEP.exe是包含在大多数资源工具包中的,例如Windows Server 2003资源工具包,该工具包也可以安装在Windows XP上。

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

15

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

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

DELAY.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

你也可以在计算中插入日期,这样当延迟时间间隔跨越午夜时,该方法也会正常工作。


15
这应该是准确的,但这是一种消耗CPU资源的方式。通常你希望采用中断驱动的实现,这样进程在等待时不会消耗CPU周期。对于不频繁的短暂等待,这不应该是问题,因为大多数批处理情况下都是如此。但是一个长时间等待的持续运行进程可能会对系统性能产生负面影响。 - dbenham
4
由于它使用系统时钟,因此精确度为一秒。如果指定了2秒,则延迟时间可以在2秒和3秒之间(实际上是2.99999...秒)任何取值。 - Peter Mortensen
@mrt,@dbenham 通过在“WAIT:”标签后立即使用“ping”方法插入500毫秒的延迟,例如“PING 1.1.1.1 -n 1 -w 500 > NUL”,可以缓解此方法消耗100% CPU时间的问题。这个改变意味着批处理文件将花费大部分时间在ping超时内,这可能不会消耗大量CPU周期。 - rossmcm
如果你查看代码,可以发现秒钟数是这样获取的: SET /A S=1%%C%%100。 如果秒钟数是 08,前面的 SET 命令会这样执行:SET /A S = 108 % 100,将 S 设置为 8;这意味着“非法数字”错误在这里__永远不会__ 发生。 你测试过了吗? - Aacini
2
@mrt:问题在于你的%TIME%使用逗号来分隔百分之一秒,而不是点!只需在DELIMS=:.,"中添加一个逗号即可... - Aacini
显示剩余9条评论

13

我遇到了类似的问题,但我只是写了一个非常简短的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;
}

12

你可以使用ping命令:

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

它将等待10秒钟。

您必须使用11的原因是第一个ping立即发送而不是一秒后。这个数字应该比您想要等待的秒数多一个。

请注意,-w 的目的不是控制发送数据包的频率,而是确保在出现网络问题时等待不超过某个时间。如果您正在ping 127.0.0.1,则不太可能出现问题,因此这可能无关紧要。

ping 命令本身通常每秒发送一个数据包。虽然这在Windows文档中并未记录,但它似乎遵循与Linux版本相同的规则(在那里有记录)。


12
如果你在谈论等待一秒钟的边界,那么几毫秒是无关紧要的。如果你在实时操作中使用cmd.exe,那么你将得到应有的结果。 - paxdiablo
1
-w 是超时值。它是等待回复的毫秒数... 不是 在ping之间等待的时间量。 - quux
问题在于,如果ping的速度更快,则您可能不需要在ping之间等待一整秒钟。因此,您的等待循环将比您预期的结束得更快。 - quux
抱歉打扰了一个旧的答案:尽管时间测试证实ping间隔确实(接近)1秒,但我想知道您是否知道这方面的参考资料?在ping文档中找不到它。 - djvg
1
@djvg,你说得对,文档中确实没有提到。只是基于观察。 - paxdiablo
显示剩余3条评论

10

7
FYI:在Windows XP中不包含“Choice”命令。该命令出现在Windows 9x中,被从XP中删除,然后在Vista及以后的版本中重新添加。 - Devin Burke
7
我完全不建议这样做。至少在我所知道的所有 CHOICE 版本中,如果有人在等待时按下按钮(有些不耐烦的人会这样做),那么选择将注册输入,并因为坏的输入发出系统蜂鸣声,停止倒计时计时器,这意味着除非他们按下 N 或 Y,否则它会挂起在那里。如果他们碰巧只按了其中之一,那么选择就在那里结束了,而不是等待 5 秒钟。此外,这个选项使用的是非常奇怪的 Vista 语法。所有正常的选择命令都应该使用 CHOICE /T:Y,5 > NUL。旧版中没有 /D 标志。 - Coding With Style
1
更糟的是,至少我所知道的CHOICE命令在不同的语言环境下具有不同的默认“是/否”按钮。因此,如果你依赖于默认的[Y,N]选择而没有明确指定它为/C:YN/C:Y,当某个人使用瑞典语的CHOICE命令时,它很可能会默认显示[J,N],这时就会出现各种问题。 - Coding With Style
1
@Coding 在Win7中测试过,如果用户按下按钮,它会发出哔哔声,但是在用户按下按钮后的额外5秒钟内仍然会超时。因此,如果用户不断按键,它将永远不会超时。此外,在我的情况下,当我使用它时,我相信隐藏了控制台,以便用户无法按下按钮。在这个系统上,没有访问Python,也没有访问删除自己的exe(如其他答案中建议的),我所能做的非常有限。那么,你会推荐什么? - mlsteeves
@mlsteeves 每个不同的Windows、DOS等都有不同的choice命令,正如所指出的那样,它通常在Xp中不可用。许多choice命令具有微妙的不同行为,甚至有不同的语法。对我来说,当我需要睡眠时,我通常使用ping命令。它很丑陋,但很可靠。 - Coding With Style

9

您可以使用Windows的 cscript WSH 层和这个 wait.js JavaScript文件:

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

2
Windows 脚本宿主可以通过组策略禁用。 - Joey

8

根据您的兼容性需求,使用 ping 命令:

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

例如,要等待5秒钟,请使用
ping -n 6 localhost >nul 2>&1

或者在Windows 7或更高版本中使用timeout命令:

timeout 6 >nul

3
-w 表示毫秒,-n 只是ping的次数, 默认的ping之间的时间间隔为1秒。 - Joey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接