web-dev-qa-db-fra.com

Dormir dans un fichier batch

Lors de l'écriture d'un fichier de commandes pour automatiser quelque chose sur une machine Windows, je devais suspendre son exécution pendant plusieurs secondes (généralement dans une boucle test/attente en attendant le démarrage d'un processus). À l'époque, la meilleure solution que je pouvais trouver utilisait le ping (je ne vous en prie pas) pour obtenir l'effet désiré. J'ai trouvé une meilleure description de celui-ci here , qui décrit un appelable "wait.bat", implémenté comme suit:

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

Vous pouvez ensuite inclure les appels à wait.bat dans votre propre fichier de commandes, en indiquant le nombre de secondes de veille.

Apparemment, le Kit de ressources Windows 2003 fournit une commande de veille de type Unix (enfin!). Entre-temps, pour ceux qui utilisent encore Windows XP, Windows 2000 ou (malheureusement) Windows NT , existe-t-il un meilleur moyen?

J'ai modifié le script sleep.py dans la réponse acceptée , afin qu'il soit défini par défaut sur une seconde si aucun argument n'est transmis sur la ligne de commande:

import time, sys

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

Si vous avez installé Python, ou ne vous en occupez pas (il a également d'autres utilisations :), créez simplement le script sleep.py script et ajoutez-le quelque part dans votre PATH:

import time, sys

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

Cela permettra des pauses inférieures à une seconde (par exemple, 1,5 s, 0,1, etc.), si vous en avez le besoin. Si vous souhaitez l'appeler en tant que sleep plutôt que sleep.py, vous pouvez ajouter l'extension .PY à votre variable d'environnement PATHEXT. Sous Windows XP, vous pouvez le modifier dans:

Poste de travail → Propriétés (menu) → Options avancées (onglet) → Variables d'environnement (bouton) → Variables système (cadre).

14
tzot

La commande timeout est disponible à partir de Windows Vista:

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

Remarque: cela ne fonctionne pas avec la redirection d'entrée - exemple trivial:

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

La méthode ping décrite ci-dessous explique comment procéder: je ne peux pas (ou ne veux pas) ajouter davantage de fichiers exécutables ou installer un autre logiciel.

Vous devriez envoyer une requête ping à quelque chose qui n’existe pas et utiliser l’indicateur -w pour qu’il échoue au bout de ce laps de temps, sans envoyer de requête à quelque chose que est il (comme localhost) -n fois. Cela vous permet de gérer le temps en moins d'une seconde, et je pense que c'est un peu plus précis.

par exemple.

(test que 1.1.1.1 n'est pas pris)

ECHO Waiting 15 seconds

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

SLEEP.exe est inclus dans la plupart des kits de ressources, par ex. Le kit de ressources Windows Server 2003 qui peut également être installé sur Windows XP.

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

Je ne suis pas d'accord avec les réponses que j'ai trouvées ici.

J'utilise la méthode suivante entièrement basée sur les capacités de Windows XP pour effectuer un délai dans un fichier de traitement par lots:

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

Vous pouvez également insérer le jour dans le calcul pour que la méthode fonctionne également lorsque l'intervalle de retard dépasse minuit.

15
Aacini

J'ai rencontré un problème similaire, mais je viens juste de faire fonctionner une application console C++ très courte pour faire la même chose. Il suffit d’exécuter MySleep.exe 1000 - peut-être plus facile que de télécharger/installer le kit de ressources complet.

#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;
}
13
John Sibly

Sur Server Fault, une question similaire a été posée , la solution proposée était:

choice /d y /t 5 > nul
10
mlsteeves

Vous pouvez utiliser le fichier Windows cscript WSH et le fichier wait.js JavaScript:

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

Selon vos besoins en matière de compatibilité, utilisez soit ping:

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

par exemple. attendre 5 secondes, utilisez 

ping -n 6 localhost >nul 2>&1

ou sous Windows 7 ou version ultérieure, utilisez timeout:

timeout 6 >nul
8
Joey

Vous pouvez utiliser le ping:

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

Il faudra attendre 10 secondes.

La raison pour laquelle vous devez utiliser 11 est que le premier ping sort immédiatement, pas après une seconde. Le nombre doit toujours être un de plus que le nombre de secondes que vous souhaitez attendre.

N'oubliez pas que le but du -w n'est pas d'attendre une seconde. C’est pour vous assurer d’attendre pas plus de plus d’une seconde en cas de problèmes de réseau. ping seul enverra un paquet ICMP par seconde. Ce n'est probablement pas nécessaire pour localhost, mais les vieilles habitudes ont la vie dure.

8
paxdiablo
timeout /t <seconds> <options>

Par exemple, pour que le script effectue une attente de 2 secondes non ininterruptible:

timeout /t 2 /nobreak >NUL

Ce qui signifie que le script attendra 2 secondes avant de continuer.

Par défaut, une frappe de touche interrompt le délai, utilisez donc le commutateur /nobreak si vous ne voulez pas que l'utilisateur puisse interrompre (annuler) l'attente. En outre, le délai d'attente fournira des notifications à la seconde pour informer l'utilisateur du temps qu'il lui reste à attendre. cela peut être supprimé en canalisant la commande vers NUL.

edit: Comme le souligne @martineaudans les commentaires , la commande timeout est uniquement disponible à partir de Windows 7. De plus, la commande ping utilise moins de temps processeur que timeout. Je pense toujours à utiliser timeout dans la mesure du possible, car il est plus lisible que le ping 'hack'. Lire plus ici .

6
mgthomas99

Il existe une meilleure façon de dormir en utilisant ping. Vous voudrez envoyer une requête ping à une adresse qui n'existe pas afin de pouvoir spécifier un délai d'attente avec une précision à la milliseconde. Heureusement, une telle adresse est définie dans une norme (RFC 3330), et il s'agit de 192.0.2.x. Ce n'est pas inventé, c'est vraiment une adresse dont le seul but est de ne pas exister (ça peut ne pas être clair, mais ça s'applique même dans les réseaux locaux):

192.0.2.0/24 - Ce bloc est affecté à "TEST-NET" pour être utilisé dans documentation et exemple de code. Il est souvent utilisé avec noms de domaine exemple.com ou exemple.net chez fournisseur et protocole Documentation. Les adresses de ce bloc ne doivent pas apparaître sur le Internet public.

Pour dormir pendant 123 millisecondes, utilisezping 192.0.2.1 -n 1 -w 123 >nul

5
mafu

Il suffit de mettre cela dans votre fichier de commandes où vous voulez attendre.

@ping 127.0.0.1 -n 11 -w 1000 > null
5
Brent Stewart

Dans le bloc-notes, écrivez:

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

Enregistrez maintenant sous wait.bat dans le dossier C:\WINDOWS\System32, Puis, chaque fois que vous voulez attendre, utilisez:

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

Si vous avez PowerShell sur votre système, vous pouvez simplement exécuter cette commande:

powershell -command "Start-Sleep -s 1"

Edit: from ma réponse sur un fil similaire , des personnes ont soulevé un problème selon lequel le temps qu’il faut à PowerShell pour démarrer est important par rapport au temps que vous attendez. Si la précision du temps d’attente est importante (c’est-à-dire qu’une ou deux secondes de retard supplémentaires ne sont pas acceptables), vous pouvez utiliser cette approche:

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

Cela prend le temps lorsque la commande windows a été émise et le script powershell dort jusqu'à 5 secondes après cette heure. Donc, tant que le démarrage de powershell prend moins de temps que la durée de votre sommeil, cette approche fonctionnera (environ 600 ms sur ma machine).

4

Le Kit de ressources a toujours inclus cela. Au moins depuis Windows 2000.

En outre, le paquet Cygwin a une sleep - plop qui dans votre PATH et inclut le cygwin.dll (ou le nom que vous appelez) et le chemin à parcourir!

4
Daren Thomas

J'aime La réponse d'Aacini . Je l'ai ajouté pour gérer la journée et lui permettre également de gérer centiseconds (%TIME% sorties 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
3
Hossy

J'utilise ce programme de sommeil C #. Cela pourrait être plus pratique pour vous si C # est votre langue préférée:

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

La meilleure solution qui devrait fonctionner sur toutes les versions de Windows après Windows 2000 serait:

timeout numbersofseconds /nobreak > nul
2
Tato

L'utilisation de ping est bonne, tant que vous voulez juste "attendre un peu". Ceci étant donné que vous dépendez d'autres fonctions sous-jacentes, telles que le fonctionnement de votre réseau et le fait qu'il n'y a aucune réponse à 127.0.0.1. ;-) Peut-être que ce n'est pas très probable que cela échoue, mais ce n'est pas impossible ... 

Si vous voulez être sûr d'attendre exactement l'heure spécifiée, vous devez utiliser la fonctionnalité sleep (qui offre également l'avantage de ne pas utiliser la puissance du processeur ou d'attendre qu'un réseau soit prêt).

Le moyen le plus pratique est de trouver un exécutable déjà créé pour le sommeil. Il suffit de le déposer dans votre dossier Windows ou dans une autre partie de votre chemin d'accès standard et il est toujours disponible.

Sinon, si vous avez un environnement de compilation, vous pouvez facilement en créer un vous-même . La fonction Sleep est disponible dans kernel32.dll, il vous suffit donc de l'utiliser. : -) Pour VB/VBA, déclarez ce qui suit au début de votre source pour déclarer une fonction de veille:

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

Pour C #:

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

Vous trouverez ici plus d'informations sur cette fonctionnalité (disponible depuis Windows 2000) dans Fonction de veille (MSDN).

En C standard, sleep() est inclus dans la bibliothèque standard et dans Visual Studio C de Microsoft, la fonction est nommée Sleep(), si la mémoire le permet. ;-) Ces deux prennent l'argument en secondes, pas en millisecondes comme les deux déclarations précédentes.

2
Tooony

Encore plus léger que la solution Python, un Perl One-liner.

Pour dormir pendant sept secondes, inscrivez ceci dans le script BAT:

Perl -e "sleep 7"

Cette solution ne fournit qu'une résolution d'une seconde.

Si vous avez besoin d’une résolution plus élevée, utilisez le module Time :: HiRes De CPAN. Il fournit usleep() qui dort en Microsecondes et nanosleep() qui dort en nanosecondes .__ (les deux fonctions ne prennent que des arguments entiers). Voir la question Stack Overflow Comment puis-je dormir une milliseconde en Perl? pour plus de détails.

J'ai utilisé ActivePerl pendant de nombreuses années. Il est très facile d'installer

2
Peter Mortensen

Ou en ligne de commande Python, par exemple, pendant 6 secondes et demie:

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

Je suis impressionné par celui-ci:

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

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

Techniquement, vous dites à la commande choice d'accepter uniquement y. Par défaut, y: le faire en 5 secondes, ne dessiner aucune invite et vider tout ce qu'il dit à NUL (comme un terminal nul sous Linux).

1
Chris Moschini

Sous Windows Vista, vous disposez des commandes TIMEOUT et SLEEP , mais pour les utiliser sous Windows XP ou Windows Server 2003, vous avez besoin du kit d'outils de ressources Windows Server 2003 .

Ici , vous avez un bon aperçu des alternatives de sommeil (l’approche ping est la plus populaire car elle fonctionnera sur toutes les machines Windows), mais il en existe (au moins) une qui ne mentionne pas qui utilise le W32TM (Service de temps):

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

Où vous devez remplacer le N par les secondes que vous souhaitez mettre en pause. En outre, cela fonctionnera sur tous les systèmes Windows sans conditions préalables.

Typeperf peut également être utilisé:

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

Le fichier pathping.exe peut dormir moins d'une seconde.

@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
1
Andry

Vous pouvez également utiliser un fichier .vbs pour effectuer des délais d'expiration spécifiques:

Le code ci-dessous crée le fichier .vbs. Mettez ceci en haut de votre code rbatch:

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

Le code ci-dessous ouvre ensuite le fichier .vbs et spécifie combien de temps attendre:

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

Dans le code ci-dessus, le "1000" est la valeur du délai à envoyer au fichier .vbs en millisecondes, par exemple, 1000 ms = 1 s. Vous pouvez modifier cette partie pour être aussi long que vous voulez.

Le code ci-dessous supprime le fichier .vbs lorsque vous avez terminé. Mettez ceci à la fin de votre fichier batch:

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

Et voici le code ensemble, il est donc facile de copier:

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

Puisque d'autres suggèrent des programmes tiers (Python, Perl, une application personnalisée, etc.), une autre option est GNU CoreUtils pour Windows disponible à l'adresse http://gnuwin32.sourceforge.net/packages/coreutils.htm .

2 options de déploiement:

  1. Installez le package complet (qui inclura la suite complète de CoreUtils, les dépendances, la documentation, etc.).
  2. Installez uniquement les dépendances binaires et nécessaires 'sleep.exe' (utilisez depend.exe pour obtenir les dépendances).

L'un des avantages du déploiement de CoreUtils est que vous aurez également accès à une foule d'autres programmes utiles pour la génération de scripts (le traitement Windows laisse beaucoup à désirer).

0
codesniffer

Vous pouvez avoir du style en mettant le message PAUSE dans la barre de titre:

@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
0
djangofan

Ceci a été testé sur Windows XP SP3 et Windows 7 et utilise CScript. J'ai mis des protections pour éviter les "" incitations. (/q serait dangereux)

Attends une seconde:

sleepOrDelayExecution 1000

Attendez 500 ms, puis lancez les commandes après:

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
0
Anonymous Coward