How to sleep in a batch file?
The correct way to sleep in a batch file is to use the
timeout command, introduced in Windows 2000.
To wait somewhere between 29 and 30 seconds:
timeout /t 30
The timeout would get interrupted if the user hits any key; however, the command also accepts the optional switch
/nobreak, which effectively ignores anything the user may press, except an explicit
timeout /t 30 /nobreak
Additionally, if you don't want the command to print its countdown on the screen, you can redirect its output to
timeout /t 30 /nobreak > NUL
Since it applies here, too, I'll copy my answer from another site.
If you want to use ping, there is a better way. 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 (it may not be clear, but it 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
You can also insert a
ping to localhost. This will take 4 seconds to complete (by default). It is considered a kludge by some, but works quite well all the same.
Disclaimer: this is not the "ideal" solution, so don't bother beating me over the head with that like done to those recommending
When possible, use
timeout for sure. But as noted in the comments, that's not always an option (e.g. in non-interactive mode). After that, I agree that the
ping "kludge" is perhaps the next best option, as it is very simple. That said, I offer another option... embed some VB Script.
The basis of this solution has all sorts of application beyond this. Often VBS can do things that batch cannot, or at the very least do so with drastically more ease. Using the technique illustrated here, you can mix the two (not "seamlessly", but "functionally"...).
Here's a one liner, to create a temp script, execute it, then delete it. The script does the sleeping for you (for 3 seconds in this example).
echo WScript.Sleep 3000 > %temp%\sleep.vbs & cscript %temp%\sleep.vbs %sleepMs% //B & del %temp%\sleep.vbs
Here's basically the same thing, written a bit differently:
set sleepMs=3000 & set sleepVbs=%temp%\sleep.vbs & echo WScript.Sleep WScript.Arguments(0) > %sleepVbs% & cscript %sleepVbs% %sleepMs% //B & del %sleepVbs%
And then finally, like
CScript itself has a timeout option! So, if you enter an infinite loop in the script, you can let the interpreter enforce the duration. Note, this is a "busy" operation, which eats the CPU, and therefore I don't recommend it when you can use the
WScript.Sleep procedure, but I present it as a conceptual option for the sake of completeness:
set sleepSec=3 & set sleepVbs=%temp%\sleep.vbs & echo While True > %sleepVbs% & echo Wend >> %sleepVbs% & cscript %sleepVbs% //B //T:%sleepSec% & del %sleepVbs%