Sleeping in a batch file

Viewed 151449

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)
34 Answers

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)

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%)

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;
}

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!

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.

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");
            }
        }
    }
}

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.

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.

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.

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

use timeout

e.g.- timeout 10 will await for 10 seconds before executing next command in cmd or powershell

There are many answers on this issue noting the use of ping, but most of them point to loopback addresses or addresses that are now seen as valid addresses for DNS.

Instead of that, you should use a TEST-NET IP address reserved for documentation use only, per the IETF.
(more information on that here)

Here is a fully commented batch script to demonstrate the use of a sleep function using 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

And of course, you can also just use the command directly if you don't want to make a function:
ping 203.0.113.0 -n 1 -w timeInMilliseconds >NUL

Related