web-dev-qa-db-fra.com

Boucle While en batch

Voici ce que je veux, à l'intérieur de BACKUPDIR, je veux exécuter cscript /nologo c:\deletefile.vbs %BACKUPDIR% jusqu'à ce que le nombre de fichiers dans le dossier soit supérieur à 21 (countfiles le maintient). Voici mon code:

@echo off
SET BACKUPDIR=C:\test
for /f %%x in ('dir %BACKUPDIR% /b ^| find /v /c "::"') do set countfiles=%%x

for %countfiles% GTR 21 (
cscript /nologo c:\deletefile.vbs %BACKUPDIR%
set /a countfiles-=%countfiles%
)
42
Hellnar
set /a countfiles-=%countfiles%

Cela va mettre countfiles à 0. Je pense que vous voulez le diminuer de 1, utilisez donc ceci à la place:

set /a countfiles-=1

Je ne suis pas sûr que la boucle for marche, essayez de faire quelque chose comme ça:

:loop
cscript /nologo c:\deletefile.vbs %BACKUPDIR%
set /a countfiles-=1
if %countfiles% GTR 21 goto loop
53
schnaader

Une boucle while peut être simulée dans cmd.exe avec:

:still_more_files
    if %countfiles% leq 21 (
        rem change countfile here
        goto :still_more_files
    )

Par exemple, le script suivant:

    @echo off
    setlocal enableextensions enabledelayedexpansion
    set /a "x = 0"

:more_to_process
    if %x% leq 5 (
        echo %x%
        set /a "x = x + 1"
        goto :more_to_process
    )

    endlocal

les sorties:

0
1
2
3
4
5

Pour votre cas particulier, je commencerais par ce qui suit. Votre description initiale était un peu déroutante. Je suppose que vous voulez supprimer les fichiers de ce répertoire jusqu'à ce qu'il y en ait 20 ou moins:

    @echo off
    set backupdir=c:\test

:more_files_to_process
    for /f %%x in ('dir %backupdir% /b ^| find /v /c "::"') do set num=%%x
    if %num% gtr 20 (
        cscript /nologo c:\deletefile.vbs %backupdir%
        goto :more_files_to_process
    )
46
paxdiablo
@echo off

set countfiles=10

:loop

set /a countfiles -= 1

echo hi

if %countfiles% GTR 0 goto loop

pause

sur le premier "set countfiles" le 10 que vous voyez est la quantité qu'il va boucler l'écho hi c'est la chose que vous voulez boucler

... j'ai 5 ans de retard

6
luke

J'ai un truc pour faire ça!

J'ai mis au point cette méthode car, dans l'interface de ligne de commande, il n'est pas possible d'utiliser les méthodes fournies dans les autres réponses ici et cela m'a toujours causé des problèmes.

J'appelle cela la boucle "Do Until Break" ou "Infinite":

Exemple de base

FOR /L %L IN (0,0,1) DO @(
 ECHO. Counter always 0, See "%L" = "0" - Waiting a split second&ping -n 1 127.0.0.1>NUL )

C'est vraiment une boucle infinie!

Ceci est utile pour surveiller quelque chose dans une fenêtre CMD, et vous permet d'utiliser CTRL + C pour le casser lorsque vous avez terminé.

Vous voulez avoir un compteur?

Soit utiliser SET /A OR Vous pouvez modifier le FOR /L Boucle pour compter et rester infini (Remarque, ces deux méthodes ont un débordement d’entier de 32 bits)

SET /A Méthode:

FOR /L %L IN (0,0,1) DO @(
 SET /A "#+=1"&ECHO. L Still equals 0, See "%L = 0"!  - Waiting a split second &ping -n 1 127.0.0.1>NUL  )

Originaire de FOR /L Compteur:

FOR /L %L IN (-2147483648,1,2147483648) DO @(
 ECHO.Current value of L: %L - Waiting a split second &ping -n 1 127.0.0.1>NUL  )

Comptage de jeux de 4294967295 et affichage de la valeur actuelle de L:

FOR /L %L IN (1,1,2147483648) DO @(
 (
  IF %L EQU 0 SET /A "#+=1">NUL
 )&SET /A "#+=0"&ECHO. Sets of 4294967295 - Current value of L: %L - Waiting a split second &ping -n 1 127.0.0.1>NUL )

Cependant, que faire si:

  • Vous souhaitez examiner la sortie du moniteur et craignez de dépasser la limite de mémoire tampon de la ligne 9999 avant de la vérifier une fois terminée.
  • Vous souhaitez entreprendre des actions supplémentaires une fois que la chose que je surveille est terminée.

Pour cela, j'ai déterminé comment utiliser plusieurs méthodes pour casser la boucle FOR et la transformer prématurément en une "DO WHILE" ou "DO UNTIL "Boucle, qui manque cruellement par ailleurs en CMD.

Remarque: la plupart du temps, une boucle continue à itérer au-delà de la condition que vous avez cochée, il s'agit souvent d'un comportement souhaité, mais pas dans notre cas.

Transformez la "boucle infinie" en "DO WHILE "/" DO UNTIL" Boucle

MISE À JOUR: En raison de vouloir utiliser ce code dans les scripts CMD (et les laisser persister!) Ainsi que dans l'interface de ligne de commande, et pour savoir s'il pourrait y avoir une méthode "plus correcte" pour y parvenir, je recommande l'utilisation de la nouvelle méthode!

Nouvelle méthode (Peut être utilisé dans les scripts CMD sans quitter le script):

FOR /F %%A IN ('
  CMD /C "FOR /L %%L IN (0,1,2147483648) DO @( ECHO.%%L & IF /I %%L EQU 10 ( exit /b  ) )"
') DO @(
  ECHO %%~A
)

À la CLI:

FOR /F %A IN ('
  CMD /C "FOR /L %L IN (0,1,2147483648) DO @( ECHO.%L & IF /I %L EQU 10 ( exit /b  ) )"
') DO @(
  ECHO %~A
)

Méthode originale (fonctionnera parfaitement sur la CLI, mais supprimera un script.)

FOR /L %L IN (0,1,2147483648) DO @(
  ECHO.Current value of L: %L - Waiting a split second &ping -n 1 127.0.0.1>NUL&(
    IF /I %L EQU 10 (
      ECHO.Breaking the Loop! Because We have matched the condition!&DIR >&0
    )
  )
) 2>NUL

Articles plus anciens

Par chance, j'avais trouvé des moyens de sortir prématurément des boucles qui ne fermaient pas l'invite du CMD lorsque j'essayais de faire d'autres choses qui me donnaient cette idée.

REMARQUE:

Tandis que ECHO.>&3 >NUL avait travaillé pour moi dans certains scénarios, j’ai joué avec cela au fil des ans et j’ai découvert que DIR >&0 >NUL était beaucoup plus cohérent.

Je suis en train de réécrire cette réponse à partir d’ici pour utiliser cette méthode à la place car j’ai récemment retrouvé la vieille note et l’utiliser à la place.

Poste édité avec une meilleure méthode suit:

DIR >&0 >NUL

Le> NUL est facultatif, je préfère simplement ne pas l'avoir en sortie de l'erreur.

Je préfère faire correspondre en ligne lorsque cela est possible, comme vous pouvez le voir dans cet exemple simplifié d'une commande que j'utilise pour surveiller les migrations de LUN sur notre VNX.

for /l %L IN (0,0,1) DO @(
   ECHO.& ECHO.===========================================& (
     [VNX CMD] | FINDSTR /R /C:"Source LU Name" /C:"State:" /C:"Time " || DIR >&0 >NUL
   ) & Ping -n 10 1.1.1.1 -w 1000>NUL )

En outre, j'ai une autre méthode que j'ai trouvée dans cette note et que je viens juste de tester à nouveau pour confirmer que cette méthode fonctionne aussi bien avec la CLI qu'avec l'autre méthode.

Apparemment, lorsque j'ai posté pour la première fois ici, j'ai posté une version plus ancienne avec laquelle je jouais au lieu des deux nouvelles qui fonctionnent mieux:

Dans cette méthode, nous utilisons EXIT /B pour quitter la boucle For, mais nous ne souhaitons pas quitter la CLI, nous l’emballons donc dans une session CMD:

FOR /F %A IN ('CMD /C "FOR /L %L IN (0,1,10000000) DO @( ECHO.%L & IF /I %L EQU 10 ( exit /b  ) )" ') DO @(ECHO %~A)

Comme la boucle elle-même se produit dans la session CMD, nous pouvons utiliser EXIT/B pour quitter l'itération de la boucle sans perdre notre session CMD et sans attendre la fin de la boucle, à peu près de la même façon qu'avec l'autre méthode.

J'irais même jusqu'à dire que cette méthode est probablement la méthode "prévue" pour le type de scénario dans lequel vous souhaitez interrompre une boucle for au niveau de la CLI, car l'utilisation de la session CMD est également le seul moyen de faire fonctionner l'expansion retardée à l'interface de ligne de commande de vos boucles, ainsi que le comportement et ce comportement est clairement un flux de travaux destiné à quitter une session CMD.

IE: Microsoft a clairement fait un effort délibéré pour que les boucles CMD Exit/B For se comportent de cette manière, tandis que la méthode "Intentionnée", comme mon autre méthode, repose sur la création accidentelle de la bonne erreur pour vous expulser de la boucle sans laisser le traitement de fin de boucle, que je n’ai découvert que de manière substantielle, et ne semble fonctionner de manière fiable que lorsqu’on utilise la commande DIR, ce qui est assez étrange.

Donc, cela dit, je pense que c'est probablement une meilleure pratique d'utiliser la méthode 2:

FOR /F %A IN ('CMD /C "FOR /L %L IN (0,1,10000000) DO @( ECHO.%L & IF /I %L EQU 10 ( exit /b  ) )" ') DO @(ECHO %~A)

Bien que je soupçonne que la Méthode 1 sera un peu plus rapide:

FOR /L %L IN (0,1,10000000) DO @( ECHO.%L & IF /I %L EQU 10 ( DIR >&) >NUL ) )

Et dans les deux cas, les deux doivent autoriser les boucles DO-While selon vos besoins.

3
Ben Personick

Il m'a été très utile d'ajouter de la manière suivante un utilisateur dans Active Directory:

:: This file is used to automatically add list of user to activedirectory
:: First ask for username,pwd,dc details and run in loop
:: dsadd user cn=jai,cn=users,dc=mandrac,dc=com -pwd `1q`1q`1q`1q

@echo off
setlocal enableextensions enabledelayedexpansion
set /a "x = 1"
set /p lent="Enter how many Users you want to create : "
set /p Uname="Enter the user name which will be rotated with number ex:ram then ram1 ..etc : "
set /p DcName="Enter the DC name ex:mandrac : "
set /p Paswd="Enter the password you want to give to all the users : "

cls

:while1

if %x% leq %lent% (

    dsadd user cn=%Uname%%x%,cn=users,dc=%DcName%,dc=com -pwd %Paswd%
    echo User %Uname%%x% with DC %DcName% is created
    set /a "x = x + 1"
    goto :while1
)

endlocal
2
jayaram