153

When writing a batch file to automate something on a Windows box, I've needed to pause its execution for several seconds (usually in a test/wait loop, waiting for a process to start). At the time, the best solution I could find uses ping (I kid you not) to achieve the desired effect. I've found a better write-up of it here, which describes a callable "wait.bat", implemented as follows:

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

You can then include calls to wait.bat in your own batch file, passing in the number of seconds to sleep.

Apparently the Windows 2003 Resource Kit provides a Unix-like sleep command (at last!). In the meantime, for those of us still using Windows XP, Windows 2000 or (sadly) Windows NT, is there a better way?

I modified the sleep.py script in the accepted answer, so that it defaults to one second if no arguments are passed on the command line:

import time, sys

time.sleep(float(sys.argv[1]) if len(sys.argv) > 1 else 1)
Community
  • 1
  • 1
Jason Etheridge
  • 6,643
  • 5
  • 27
  • 32
  • The 2003 server resource kit works with Windows XP (and probably with w2k) – Martin Beckett Jul 07 '09 at 14:41
  • http://stackoverflow.com/questions/5437201/how-to-wait-in-a-batch-script/5822491 http://stackoverflow.com/questions/1304738/wait-in-console http://stackoverflow.com/questions/4908495/pausing-a-batch-file-for-amount-of-time http://stackoverflow.com/questions/166044/sleeping-in-a-dos-batch-file – Chris Moschini Apr 28 '11 at 18:16
  • Here's some options for [batch file wait](http://www.robvanderwoude.com/wait.php) – Unknown_Guy Mar 25 '11 at 19:41
  • Check: *[Implementing the WAIT Command in a Batch File](http://malektips.com/dos0017.html)* *[Batch file SLEEP Command](http://malektips.com/xp_dos_0002.html)* – Wael Dalloul Aug 20 '09 at 08:28
  • The Microsoft [download page](http://www.microsoft.com/downloads/details.aspx?FamilyID=9d467a69-57ff-4ae7-96ee-b18c4790cffd&DisplayLang=en) of the Windows 2003 Resource Kit indicates that it also works for XP. I'm afraid there is no other choice but to use an 'external' utility to do the waiting: there is nothing like this built into the XP command processor. – GerG Oct 03 '08 at 09:22
  • 2
    You have a couple of options - emulate a sleep with the [`ping`](http://malektips.com/dos0017.html) command, or download the windows resource kit which includes a `sleep` command. More details here: [Batch file SLEEP Command](http://malektips.com/xp_dos_0002.html) – Rudu Mar 25 '11 at 19:30
  • I faced the same problem in the past, and used ping myself (with a remark above clearly documenting that I realize this is stupid :) ). – Jack Leow Jul 07 '09 at 14:47
  • State `%1` rather than `%1%` to refer to the first command line argument... – aschipfl Jan 26 '17 at 14:23
  • A good summary of the various techniques to halt a batch file process: https://www.robvanderwoude.com/wait.php – 1934286 Jan 03 '19 at 01:32

32 Answers32

231

The timeout command is available from Windows Vista onwards:

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

Note: It does not work with input redirection - trivial example:

C:\>echo 1 | timeout /t 1 /nobreak
ERROR: Input redirection is not supported, exiting the process immediately.
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Blorgbeard
  • 93,378
  • 43
  • 217
  • 263
  • 8
    does not work in console-less uses: "ERROR: Input redirection is not supported, exiting the process immediately." – simpleuser Aug 27 '13 at 23:01
  • I meant cases where you don't have a console at all, such as when the batch file is run in the background via a fork from some other process, a cygwin crontab, or remote ssh command, etc. – simpleuser Aug 30 '13 at 03:08
  • 1
    Oh yeah I know. The example i gave was just to demonstrate the error :) – Blorgbeard Aug 30 '13 at 04:35
  • 3
    The [link](http://technet.microsoft.com/en-us/library/cc754891.aspx) to the documentation for `timeout`, added by @Cristian Ciupitu, is partially wrong -- Windows XP doesn't have this command. – martineau Apr 02 '14 at 19:49
  • Timeout didn't work for me without specifying the full path: c:\windows\system32\timeout – Hello World Jun 03 '14 at 09:00
  • 1
    @HelloWorld that sounds like an issue with your %PATH% – Blorgbeard Jun 30 '14 at 20:18
  • according to https://stackoverflow.com/a/1672375/496289, `timeout` is not precise. – Kashyap Aug 02 '20 at 20:36
21

Using the ping method as outlined is how I do it when I can't (or don't want to) add more executables or install any other software.

You should be pinging something that isn't there, and using the -w flag so that it fails after that amount of time, not pinging something that is there (like localhost) -n times. This allows you to handle time less than a second, and I think it's slightly more accurate.

e.g.

(test that 1.1.1.1 isn't taken)

ECHO Waiting 15 seconds

PING 1.1.1.1 -n 1 -w 15000 > NUL
  or
PING -n 15 -w 1000 127.1 >NUL
djangofan
  • 25,461
  • 54
  • 171
  • 262
daniel
  • 463
  • 1
  • 4
  • 12
17

UPDATE

The timeout command, available from Windows Vista and onwards should be the command used, as described in another answer to this question. What follows here is an old answer.

Old answer

If you have Python installed, or don't mind installing it (it has other uses too :), just create the following sleep.py script and add it somewhere in your PATH:

import time, sys

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

It will allow sub-second pauses (for example, 1.5 sec, 0.1, etc.), should you have such a need. If you want to call it as sleep rather than sleep.py, then you can add the .PY extension to your PATHEXT environment variable. On Windows XP, you can edit it in:

My Computer → Properties (menu) → Advanced (tab) → Environment Variables (button) → System variables (frame)

Community
  • 1
  • 1
tzot
  • 81,264
  • 25
  • 129
  • 197
  • 32
    why should we write a script in python when batch-scriptable solution is requested? How can path extension solve the problem that Windows users have no python interpreter installed? Thanks. – Val Oct 19 '12 at 16:17
  • 6
    For portability sake, I think this solution should be avoided as there are perfectly fine native alternatives. – Gras Double Aug 07 '17 at 00:45
  • 1
    This approach might have provided a workaround in the past, but the native solution described by @Blorgbeard is definitely the way to go. – Mike May 31 '19 at 12:43
16

SLEEP.exe is included in most Resource Kits e.g. The Windows Server 2003 Resource Kit which can be installed on Windows XP too.

Usage:  sleep      time-to-sleep-in-seconds
        sleep [-m] time-to-sleep-in-milliseconds
        sleep [-c] commited-memory ratio (1%-100%)
Cristian Ciupitu
  • 18,164
  • 7
  • 46
  • 70
Luk
  • 4,983
  • 4
  • 35
  • 54
15

I disagree with the answers I found here.

I use the following method entirely based on Windows XP capabilities to do a delay in a batch file:

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

You may also insert the day in the calculation so the method also works when the delay interval pass over midnight.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Aacini
  • 59,374
  • 12
  • 63
  • 94
  • 15
    This should be accurate, but it is a CPU intensive way to go about it. Normally you want an interupt driven implementation so that the process does not consume CPU cycles while it waits. This shouldn't be a problem for infrequent short waits, as is probably the case for most batch situations. But a continuously running process with long waits could have a negative impact on system performance. – dbenham Feb 15 '12 at 21:43
  • 4
    As it uses the system clock the accuracy is one second. If 2 seconds is specified, the delay can be anything between 2 seconds and 3 seconds (actually 2.99999... seconds). – Peter Mortensen Aug 15 '12 at 06:49
  • What if the time is now 7:59:59 and you want to wait 7 seconds? This looks like it doesn't take that into account. – ashes999 Sep 28 '12 at 18:45
  • This consumes more CPU time than it counts system time. In addition you are doing arithmetic operations with octal numbers, since minutes and seconds smaller than 10 are displayed with a leading 0 in the `TIME` command. – Andreas Mar 01 '13 at 15:32
  • @mrt: If you review my solution, you'll realize that it correctly manage minutes and seconds with a leading zero... – Aacini Mar 01 '13 at 23:59
  • Yes I noticed the modulo operation, yet the script always gives me this error various times: `Illegal number. Numeric constants are either decimal (17), hexadecimal (0x11) or octal (021) numbers`. – Andreas Mar 02 '13 at 09:22
  • @mrt, @dbenham The issue of this method consuming 100% of CPU time can be mitigated by inserting a delay of say, 500 mS using the `ping` method immediately after the `WAIT:` label, e.g. `PING 1.1.1.1 -n 1 -w 500 > NUL`. This change will mean that the batch file spends the vast majority of it's time inside the ping timeout, which presumably doesn't consume significant CPU cycles. – rossmcm Jun 22 '15 at 02:00
  • The `illegal number` script error is because in a `set` command, batch assumes any numeric literal starting with `0` is _octal_, so `08` and `09` trip it up. I just add a couple of check statements, so if I want to get the number of seconds from the current time: `set Secs=%time:~6,2%`, `if %Secs%==08 set Secs=8`, `if %Secs%==09 set Secs=9`. – rossmcm Jun 22 '15 at 02:12
  • @rossmcm: If you review the code, the seconds are taken this way: `SET /A S=1%%C%%100`. If the seconds are `08`, previous SET command is executed this way: `SET /A S = 108 % 100` that set S = 8; this means that `Illegal number` error _never_ happen here. Did you tested it? – Aacini Jun 22 '15 at 02:23
  • @Aacini I tested your script and it always returns an error: `C:\Temp>delay.bat 5 Ungültige Zahl. Numerische Konstanten sind entweder dezimale (17), hexadezimale (0x11) oder oktale (021) Zahlen.` The error message says that a number is invalid. The delay seems to work, though. – Andreas Jun 22 '15 at 05:59
  • @mrt: This is strange. Could you remove the `@ECHO OFF` line, run the code with 1 second and post the FOR and SET lines that issue the error, please? For example: `FOR /F "TOKENS=1-3 DELIMS=:." %A IN (" 6:56:34.14") DO SET /A H=%A, M=1%B%100,S=1%C%100, CURRENT=(H*60+M)*60+S` and `SET /A H= 6, M=156%100, S=134%100, CURRENT=(H*60+M)*60+S`. – Aacini Jun 22 '15 at 12:03
  • @rossmcm: Could you confirm if you get `illegal number` error from this Batch file and post the same data I requested in previous comment, please? TIA – Aacini Jun 22 '15 at 12:08
  • @Aacini Uh that's strange! When removing `@echo off`, no error message is printed. Here's the output: http://pasted.co/757bf8f7 – Andreas Jun 22 '15 at 14:01
  • 2
    @mrt: The problem is that your `%TIME%` use a comma to separate the centiseconds, instead of a point! Just add a comma in `DELIMS=:.,"`... – Aacini Jun 22 '15 at 14:14
13

I faced a similar problem, but I just knocked up a very short C++ console application to do the same thing. Just run MySleep.exe 1000 - perhaps easier than downloading/installing the whole resource kit.

#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;
}
John Sibly
  • 21,309
  • 7
  • 55
  • 78
10

Over at Server Fault, a similar question was asked, and the solution there was:

choice /d y /t 5 > nul
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
mlsteeves
  • 1,231
  • 2
  • 16
  • 20
  • 7
    FYI: Choice is not included in Windows XP. It was in Windows 9x, removed from XP, and added back for Vista onward. – Devin Burke Apr 04 '11 at 21:58
  • 7
    I do not recommended this at all. At least in all the `CHOICE` versions I know, if someone hits a button while waiting, which impatient folks do sometimes, then choice will register an input, give a system beep for a bad input, and halt the countdown timer, which means it will hang there unless they push N or Y. And if they just happen to push one of those two, then the choice ends right there instead of waiting for 5. Also, this choice is using really weird Vista syntax. All the normal choice commands would instead use `CHOICE /T:Y,5 > NUL` for that. There is no `/D` flag in the old versions. – Coding With Style Jun 25 '11 at 23:00
  • 1
    To top it off, at least the CHOICE commands I know have different default yes/no buttons based on the language it came in, so if you happen to rely on a default [Y,N] choice instead of explicitly specifying it with `/C:YN` or just `/C:Y`, this is not going to work when someone happens to have, say, a Swedish choice command which will probably do a [J,N] by default. So this is mired in all sorts of trouble. – Coding With Style Jun 25 '11 at 23:04
  • 1
    @Coding Tested this in Win7, and if the user presses a button, it will beep, however it will still timeout after an additional 5 seconds after the user pressed a button. So if the user keeps pressing keys, it will never timeout. Also, in my case, when I used this, I believe that hide the console, so that the user couldn't press the button. On this system, there was no access to Python, there was no access to drop my own exe on the system (as suggested in some other answers), I was pretty limited in what I could do. So, What would you recommend? – mlsteeves Jun 28 '11 at 17:14
  • @mlsteeves Every different Windows, DOS, etc. has a different choice command and as noted it is not normally available in Xp. Many choice commands have subtly different behavior and some even have different syntax. Me, I generally use the ping command when I need a sleep. It's ugly, but reliable. – Coding With Style Mar 18 '13 at 22:34
9

You could use the Windows cscript WSH layer and this wait.js JavaScript file:

if (WScript.Arguments.Count() == 1)
    WScript.Sleep(WScript.Arguments(0)*1000);
else
    WScript.Echo("Usage: cscript wait.js seconds");
Blake7
  • 2,087
  • 1
  • 16
  • 8
8

You can use ping:

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

It will wait 10 seconds.

The reason you have to use 11 is because the first ping goes out immediately, not after one second. The number should always be one more than the number of seconds you want to wait.

Keep in mind that the purpose of the -w is not to wait one second. It's to ensure that you wait no more than one second in the event that there are network problems. ping on its own will send one ICMP packet per second. It's probably not required for localhost, but old habits die hard.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
paxdiablo
  • 772,407
  • 210
  • 1,477
  • 1,841
  • it is not recommended to use this for critical real-time processing. because PING command is being used, it is possible that this WAIT batch file may run over a few milliseconds – Wael Dalloul Aug 20 '09 at 08:31
  • 12
    @Wael, if you're talking about waiting on one-second boundaries, a few milliseconds will be irrelevant. And if you're using cmd.exe for realtime stuff, you deserve everything you get :-) – paxdiablo Aug 20 '09 at 08:34
  • -w is a timeout value. It's the number of milliseconds to wait for a reply ... *not* the amount of time to wait *between* pings. – quux Jul 29 '11 at 08:39
  • @quux, nowhere did I state `-w` was the timeout (though I admit some may infer that due to my lack of clarity), it's actually used to limit the cycle time where there are network problems which would cause each cycle to take _more_ than its allocated second. I've added a paragraph to the end to clarify this. – paxdiablo Jul 29 '11 at 09:54
  • issue is that if pings return *faster*, you may not wait one full second between pings. so your wait loop will end faster than you thought it would – quux Aug 01 '11 at 19:42
  • @quux, ping itself has an interval of one second. The fact tha ICMP replies come back in milliseconds doesn't change this. You can change the interval (at least on Linux) but the default is one second. Hence your concern re fast replies is unfounded. – paxdiablo Aug 01 '11 at 22:23
8

Depending on your compatibility needs, either use ping:

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

e.g. to wait 5 seconds, use

ping -n 6 localhost >nul 2>&1

or on Windows 7 or later use timeout:

timeout 6 >nul
Joey
  • 316,376
  • 76
  • 642
  • 652
  • 2
    `-w` is in milliseconds, `-n` is just the number of times to ping and the default time between pings is a second. – Joey Jan 08 '15 at 08:32
7

If you've got PowerShell on your system, you can just execute this command:

powershell -command "Start-Sleep -s 1"

Edit: from my answer on a similar thread, people raised an issue where the amount of time powershell takes to start is significant compared to how long you're trying to wait for. If the accuracy of the wait time is important (ie a second or two extra delay is not acceptable), you can use this approach:

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

This takes the time when the windows command was issued, and the powershell script sleeps until 5 seconds after that time. So as long as powershell takes less time to start than your sleep duration, this approach will work (it's around 600ms on my machine).

Community
  • 1
  • 1
Niall Connaughton
  • 14,009
  • 10
  • 50
  • 46
7

There is a better way to sleep using ping. You'll want to ping an address that does not exist, so you can specify a timeout with millisecond precision. Luckily, such an address is defined in a standard (RFC 3330), and it is 192.0.2.x. This is not made-up, it really is an address with the sole purpose of not-existing. To be clear, this applies even in local networks.

192.0.2.0/24 - This block is assigned as "TEST-NET" for use in documentation and example code. It is often used in conjunction with domain names example.com or example.net in vendor and protocol documentation. Addresses within this block should not appear on the public Internet.

To sleep for 123 milliseconds, use ping 192.0.2.1 -n 1 -w 123 >nul

Update: As per the comments, there is also 127.255.255.255.

mafu
  • 28,708
  • 38
  • 138
  • 232
  • Yes, this is easier to write and understand than having to ***add one*** to the `-n` parameter. – Peter Mortensen Apr 17 '17 at 18:51
  • However, I have measured it (using 100 pings). If I use -n 3 -w 124, the actual time is exactly (3+1)*(124+1) = 4*125 = 500 ms. The timing is surprisingly stable, exact to the 10 ms resolution in the readout (by a CMD prompt with time) - and the underlying resolution is definitely better than 10 ms (not affected by the usual 16 ms tick resolution). – Peter Mortensen Apr 17 '17 at 22:22
  • @mafu That 192.0.2.0/24 should not be used does not mean it cannot be used and therefore it is not really guaranteed that there is no reply on the echo request(s). For example configure for any Windows PC the static IPv4 address 192.0.2.1 and the subnet mask 255.255.255.0 and connect the network adapter to any other device. A simple switch is enough on which nothing else is connected. Then run `ping 192.0.2.1` on this Windows PC and it can be seen that Windows TCP/IP stack replies on the echo requests. How many people know that 192.0.2.0/24 should not be used for a static IPv4 address? – Mofi Jul 03 '19 at 08:08
  • 2
    Per the discussion in the comments [here](https://stackoverflow.com/a/56863626/1945651), it seems that 192.0.2.1 is not all that foolproof and some are suggesting that 127.255.255.255 is a better choice. Thoughts? – JLRishe Jul 04 '19 at 04:04
  • The comments mentioned in the post above have now been removed (probably as NLN), but I would agree with the change to `127.255.255.255` due to it being a broadcast loopback address in Windows which is already assigned to by default (You can confirm this by running `route print` in cmd and looking through the IPv4 route table it prints). – Hoppeduppeanut Jul 08 '19 at 23:00
7
timeout /t <seconds> <options>

For example, to make the script perform a non-uninterruptible 2-second wait:

timeout /t 2 /nobreak >NUL

Which means the script will wait 2 seconds before continuing.

By default, a keystroke will interrupt the timeout, so use the /nobreak switch if you don't want the user to be able to interrupt (cancel) the wait. Furthermore, the timeout will provide per-second notifications to notify the user how long is left to wait; this can be removed by piping the command to NUL.

edit: As @martineau points out in the comments, the timeout command is only available on Windows 7 and above. Furthermore, the ping command uses less processor time than timeout. I still believe in using timeout where possible, though, as it is more readable than the ping 'hack'. Read more here.

mgthomas99
  • 2,960
  • 1
  • 16
  • 20
  • 2
    [Apparently](http://ss64.com/nt/timeout.html) this command is only available in Windows 7/2008 and the XP Resource Kit (and possibly 8/8.1). The source also claims the `ping` approach uses less processor time. – martineau Jun 04 '14 at 04:25
5

Just put this in your batch file where you want the wait.

@ping 127.0.0.1 -n 11 -w 1000 > null
Brent Stewart
  • 1,800
  • 13
  • 20
4

In Notepad, write:

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

Now save as wait.bat in the folder C:\WINDOWS\System32, then whenever you want to wait, use:

CALL WAIT.bat <whole number of seconds without quotes>
martineau
  • 99,260
  • 22
  • 139
  • 249
SuperKael
  • 216
  • 1
  • 11
  • It pings itself repeatedly, waiting a second between each ping, and then it returns to the calling program, i don't see the infinite loop, but i have tested it myself. – SuperKael Jan 28 '13 at 15:03
  • My mistake, there's no infinite loop. However, as mentioned in one of the [other answers](http://stackoverflow.com/a/6852798/355230), it's better to `ping` something not just once, and use the `-w Timeout` option for the delay-time in milliseconds rather than the `-n Count` whole number-of-retries option. – martineau Jan 28 '13 at 17:25
  • `-w Timeout` may be better, but i made sure it pings one more time than the time entered. – SuperKael Jan 28 '13 at 17:59
4

The Resource Kit has always included this. At least since Windows 2000.

Also, the Cygwin package has a sleep - plop that into your PATH and include the cygwin.dll (or whatever it's called) and way to go!

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Daren Thomas
  • 61,662
  • 38
  • 143
  • 192
  • 2
    Note that cygwin1.dll does not peacefully coexist with different versions of itself. You better have one and only one cygwin1.dll on your machine, or you will get weird failures. – JesperE Oct 03 '08 at 09:44
  • Which Resource Kit? There seems to be more than one. Can you update your answer? – Peter Mortensen Apr 17 '17 at 18:28
3

I have been using this C# sleep program. It might be more convenient for you if C# is your preferred language:

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");
            }
        }
    }
}
Blorgbeard
  • 93,378
  • 43
  • 217
  • 263
Liam
  • 17,556
  • 23
  • 76
  • 110
3

Even more lightweight than the Python solution is a Perl one-liner.

To sleep for seven seconds put this in the BAT script:

perl -e "sleep 7"

This solution only provides a resolution of one second.

If you need higher resolution then use the Time::HiRes module from CPAN. It provides usleep() which sleeps in microseconds and nanosleep() which sleeps in nanoseconds (both functions takes only integer arguments). See the Stack Overflow question How do I sleep for a millisecond in Perl? for further details.

I have used ActivePerl for many years. It is very easy to install.

Community
  • 1
  • 1
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
3

I like Aacini's response. I added to it to handle the day and also enable it to handle centiseconds (%TIME% outputs 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
Community
  • 1
  • 1
Hossy
  • 135
  • 1
  • 8
2

The usage of ping is good, as long as you just want to "wait for a bit". This since you are dependent on other functions underneath, like your network working and the fact that there is nothing answering on 127.0.0.1. ;-) Maybe it is not very likely it fails, but it is not impossible...

If you want to be sure that you are waiting exactly the specified time, you should use the sleep functionality (which also have the advantage that it doesn't use CPU power or wait for a network to become ready).

To find an already made executable for sleep is the most convenient way. Just drop it into your Windows folder or any other part of your standard path and it is always available.

Otherwise, if you have a compiling environment you can easily make one yourself. The Sleep function is available in kernel32.dll, so you just need to use that one. :-) For VB / VBA declare the following in the beginning of your source to declare a sleep function:

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

For C#:

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

You'll find here more about this functionality (available since Windows 2000) in Sleep function (MSDN).

In standard C, sleep() is included in the standard library and in Microsoft's Visual Studio C the function is named Sleep(), if memory serves me. ;-) Those two takes the argument in seconds, not in milliseconds as the two previous declarations.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Tooony
  • 3,323
  • 2
  • 15
  • 13
  • 1
    Sleep is available in the .net framework - have a look at the thread class, e.g.: using System.Threading; .... Thread.Sleep(1000); – John Sibly Oct 03 '08 at 13:01
  • 2
    If "ping 127.0.0.1" fails, you have more serious stuff than "sleep" to worry about - this is the loopback interface, anything RPC will probably go mad. – Piskvor left the building Apr 04 '09 at 18:26
2

The best solution that should work on all Windows versions after Windows 2000 would be:

timeout numbersofseconds /nobreak > nul
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Tato
  • 21
  • 1
  • Doesn't work on XP Pro...`'timeout' is not recognized as an internal or external command, operable program or batch file.` – martineau Mar 29 '14 at 01:13
2

Or command line Python, for example, for 6 and a half seconds:

python -c "import time;time.sleep(6.5)"
Alex Robinson
  • 549
  • 4
  • 4
1

From Windows Vista on you have the TIMEOUT and SLEEP commands, but to use them on Windows XP or Windows Server 2003, you'll need the Windows Server 2003 resource tool kit.

Here you have a good overview of sleep alternatives (the ping approach is the most popular as it will work on every Windows machine), but there's (at least) one not mentioned which (ab)uses the W32TM (Time Service) command:

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

Where you should replace the N with the seconds you want to pause. Also, it will work on every Windows system without prerequisites.

Typeperf can also be used:

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

With mshta and javascript (can be used for sleep under a second):

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

This should be even more precise (for waiting under a second) - self compiling executable relying on .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);
}
npocmaka
  • 51,748
  • 17
  • 123
  • 166
1

You can also use a .vbs file to do specific timeouts:

The code below creates the .vbs file. Put this near the top of you rbatch code:

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

The code below then opens the .vbs and specifies how long to wait for:

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

In the above code, the "1000" is the value of time delay to be sent to the .vbs file in milliseconds, for example, 1000 ms = 1 s. You can alter this part to be however long you want.

The code below deletes the .vbs file after you are done with it. Put this at the end of your batch file:

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

And here is the code all together so it's easy to copy:

echo WScript.sleep WScript.Arguments(0) >"%cd%\sleeper.vbs"
start /WAIT "" "%cd%\sleeper.vbs" "1000"
del /f /q "%cd%\sleeper.vbs"
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
1

The pathping.exe can sleep less than second.

@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
Andry
  • 1,237
  • 13
  • 21
1

I am impressed with this one:

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

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

Technically, you're telling the choice command to accept only y. It defaults to y, to do so in 5 seconds, to draw no prompt, and to dump anything it does say to NUL (like null terminal on Linux).

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Chris Moschini
  • 33,398
  • 18
  • 147
  • 176
  • 3
    I'll echo myself here: I do not recommended this at all. In the `CHOICE` versions I know, if someone hits a key while waiting, which impatient folks do sometimes, then choice will read an input, give a system beep for a bad input, and halt the countdown, so it will hang unless they push Y. And if they just happen to push Y, then the choice ends right there instead of waiting for 5. Also, this choice is using really weird Vista syntax. The normal choice commands instead use `CHOICE /T:Y,5 > NUL` for that. (There is no /D flag in the old versions.) And if you have Vista, use `TIMEOUT` instead. – Coding With Style Jun 25 '11 at 23:11
1

There are lots of ways to accomplish a 'sleep' in cmd/batch:

My favourite one:

TIMEOUT /NOBREAK 5 >NUL 2>NUL

This will stop the console for 5 seconds, without any output.

Most used:

ping localhost -n 5 >NUL 2>NUL

This will try to make a connection to localhost 5 times. Since it is hosted on your computer, it will always reach the host, so every second it will try the new every second. The -n flag indicates how many times the script will try the connection. In this case is 5, so it will last 5 seconds.

Variants of the last one:

ping 1.1.1.1 -n 5 >nul

In this script there are some differences comparing it with the last one. This will not try to call localhost. Instead, it will try to connect to 1.1.1.1, a very fast website. The action will last 5 seconds only if you have an active internet connection. Else it will last approximately 15 to complete the action. I do not recommend using this method.

ping 127.0.0.1 -n 5 >nul

This is exactly the same as example 2 (most used). Also, you can also use:

ping [::1] -n 5 >nul

This instead, uses IPv6's localhost version.

There are lots of methods to perform this action. However, I prefer method 1 for Windows Vista and later versions and the most used method (method 2) for earlier versions of the OS.

Lumito
  • 427
  • 4
  • 17
0

You can get fancy by putting the PAUSE message in the title bar:

@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
djangofan
  • 25,461
  • 54
  • 171
  • 262
0

This was tested on Windows XP SP3 and Windows 7 and uses CScript. I put in some safe guards to avoid del "" prompting. (/q would be dangerous)

Wait one second:

sleepOrDelayExecution 1000

Wait 500 ms and then run stuff after:

sleepOrDelayExecution 500 dir \ /s

sleepOrDelayExecution.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
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
0

Since others are suggesting 3rd party programs (Python, Perl, custom app, etc), another option is GNU CoreUtils for Windows available at http://gnuwin32.sourceforge.net/packages/coreutils.htm.

2 options for deployment:

  1. Install full package (which will include the full suite of CoreUtils, dependencies, documentation, etc).
  2. Install only the 'sleep.exe' binary and necessary dependencies (use depends.exe to get dependencies).

One benefit of deploying CoreUtils is that you'll additionally get a host of other programs that are helpful for scripting (Windows batch leaves a lot to be desired).

codesniffer
  • 733
  • 5
  • 15
0

Just for fun, if you have Node.js installed, you can use

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

to sleep for 5 seconds. It works on a Mac with Node v12.14.0.

nonopolarity
  • 130,775
  • 117
  • 415
  • 675
-2
ping -n X 127.0.0.1 > nul

Replace X with the number of seconds + 1.

For example, if you were to wait 10 seconds, replace X with 11. To wait 5 seconds, use 6.

Read earlier answers for milliseconds.