65 Stimmen

While-Schleife im Stapel

Hier ist, was ich will, innerhalb der BACKUPDIR Ich möchte Folgendes ausführen cscript /nologo c:\deletefile.vbs %BACKUPDIR% bis die Anzahl der Dateien innerhalb des Ordners größer als 21 ist( countfiles hält sie). Hier ist mein 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%
)

69voto

schnaader Punkte 47961
set /a countfiles-=%countfiles%

Dies setzt countfiles auf 0. Ich denke, Sie wollen es um 1 verringern, also verwenden Sie stattdessen dies:

set /a countfiles-=1

Ich bin mir nicht sicher, ob die for-Schleife funktioniert, versuchen Sie lieber etwas wie das hier:

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

65voto

paxdiablo Punkte 809679

A while Schleife kann simuliert werden in cmd.exe mit:

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

Zum Beispiel das folgende Skript:

    @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

Ausgänge:

0
1
2
3
4
5

In Ihrem speziellen Fall würde ich mit den folgenden Punkten beginnen. Ihre anfängliche Beschreibung war ein wenig verwirrend. Ich nehme an, Sie wollen die Dateien in diesem Verzeichnis löschen, bis es 20 oder weniger sind:

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

15voto

Ben Personick Punkte 2800

Ich habe einen Trick, um dies zu tun!

Ich habe mir diese Methode ausgedacht, weil es in der CLI nicht möglich ist, die Methoden zu verwenden, die in den anderen Antworten hier angegeben sind, und das hat mich immer gestört.

Ich nenne dies die "Do Until Break" oder "Endlosschleife":

Grundlegendes Beispiel

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 )

Dies ist wirklich eine Endlosschleife!

Dies ist nützlich für die Überwachung von etwas in einer CMD Fenster und ermöglicht Ihnen die Verwendung von CTRL + C um sie zu brechen, wenn du fertig bist.

Möchten Sie einen Zähler haben?

Entweder verwenden Sie SET /A ODER Sie können die FOR /L Schleife, um die Zählung durchzuführen und trotzdem unendlich zu sein (Achtung, bei BEIDEN dieser Methoden kommt es zu einem 32-Bit-Integer-Überlauf)

SET /A Methode:

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  )

Einheimische FOR /L Zähler:

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  )

Zählen von Mengen von 4294967295 und Anzeigen des aktuellen Werts von 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 )

Was aber, wenn:

  • Sie sind daran interessiert, die Ausgabe des Monitors zu überprüfen, und befürchten, dass ich die Puffergrenze von 9999 Zeilen überschreite, bevor ich sie nach Abschluss des Vorgangs prüfe.
  • Sie möchten einige zusätzliche Maßnahmen ergreifen, sobald die Sache, die ich überwache, abgeschlossen ist.

Zu diesem Zweck habe ich eine Reihe von Methoden entwickelt, mit denen sich die FOR Schleife vorzeitig in eine " DO WHILE " oder " DO UNTIL " Schleife, die sonst in CMD fehlt.

HINWEIS: In den meisten Fällen wird eine Schleife nach der überprüften Bedingung weiterlaufen, was oft erwünscht ist, aber nicht in unserem Fall.

Verwandeln Sie die "Endlosschleife" in eine " DO WHILE " / " DO UNTIL " Schleife

UPDATE: Da ich diesen Code sowohl in CMD-Skripten als auch in CLI-Skripten verwenden möchte (und diese bestehen bleiben sollen!) und ich überlege, ob es eine "korrektere" Methode gibt, um dies zu erreichen, empfehle ich die Verwendung der neuen Methode!

Neue Methode (Kann innerhalb von CMD-Skripten verwendet werden, ohne das Skript zu beenden):

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
)

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

Ursprüngliche Methode (Funktioniert mit CLI einwandfrei, wird aber ein Skript zerstören).

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

Älterer Beitrag Sachen

Durch Zufall war ich auf einige Möglichkeiten gestoßen, Schleifen vorzeitig zu beenden, ohne die CMD-Eingabeaufforderung zu schließen, wenn ich versuchte, andere Dinge zu tun, was mich auf diese Idee brachte.

HINWEIS:

Während ECHO.>&3 >NUL für mich in einigen Szenarien funktioniert hat, habe ich im Laufe der Jahre immer wieder damit gespielt und festgestellt, dass DIR >&0 >NUL war viel konsistenter.

Ich schreibe diese Antwort ab jetzt neu und verwende stattdessen diese Methode, da ich vor kurzem die alte Notiz an mich selbst gefunden habe, stattdessen diese Methode zu verwenden.

Bearbeiteter Beitrag mit besserer Methode folgt:

DIR >&0 >NUL

Das >NUL ist optional, ich ziehe es nur vor, dass der Fehler nicht ausgegeben wird.

Ich ziehe es vor, inLine abzustimmen, wenn dies möglich ist, wie Sie in diesem bereinigten Beispiel eines Befehls sehen können, den ich zur Überwachung von LUN-Migrationen auf unserer VNX verwende.

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 )

Außerdem habe ich eine weitere Methode, die ich in dieser Notiz an mich selbst gefunden habe und die ich gerade erneut getestet habe, um zu bestätigen, dass sie am CLI genauso gut funktioniert wie die andere Methode.

Offensichtlich habe ich, als ich hier zum ersten Mal gepostet habe, eine ältere Version gepostet, mit der ich gespielt habe, anstatt die beiden neueren, die besser funktionieren:

Bei dieser Methode verwenden wir EXIT /B um die For-Schleife zu beenden, aber wir wollen die CLI nicht beenden, also verpacken wir sie in eine CMD-Sitzung:

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)

Da die Schleife selbst in der CMD-Sitzung abläuft, können wir EXIT /B verwenden, um die Iteration der Schleife zu beenden, ohne unsere CMD-Sitzung zu verlieren und ohne auf den Abschluss der Schleife zu warten, ähnlich wie bei der anderen Methode.

Ich würde so weit gehen zu sagen, dass diese Methode ist wahrscheinlich die "beabsichtigte" Methode für die Art von Szenario, in dem Sie eine for-Schleife an der CLI zu brechen, wie mit CMD-Sitzung ist auch der einzige Weg, um Delayed Expansion arbeiten an der CLI für Ihre Schleifen, und das Verhalten und ein solches Verhalten ist eindeutig eine beabsichtigte Workflow zu verlassen eine CMD-Sitzung.

IE: Microsoft hat offensichtlich absichtlich dafür gesorgt, dass sich CMD Exit /B For-Schleifen auf diese Weise verhalten, während die "beabsichtigte" Methode, wie meine andere Methode, darauf beruht, dass man versehentlich genau den richtigen Fehler erzeugt hat, der einen aus der Schleife wirft, ohne dass die Schleife zu Ende verarbeitet wird, was ich nur zufällig entdeckt habe, und es scheint nur zuverlässig zu funktionieren, wenn man den Befehl DIR verwendet, was ziemlich seltsam ist.

Daher halte ich es für die bessere Praxis, Methode 2 anzuwenden:

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)

Obwohl ich vermute, dass Methode 1 etwas schneller sein wird:

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

Und in jedem Fall sollten beide DO-While-Schleifen zulassen, die Sie für Ihre Zwecke benötigen.

10voto

luke Punkte 81
@echo off

set countfiles=10

:loop

set /a countfiles -= 1

echo hi

if %countfiles% GTR 0 goto loop

pause

beim ersten "set countfiles" ist die 10, die Sie sehen, die Anzahl, die in einer Schleife ausgeführt wird das Echo hi ist das, was Sie durchschleifen wollen

...ich bin 5 Jahre zu spät

2voto

jayaram Punkte 21

Es war sehr nützlich für mich, ich habe in der folgenden Weise verwendet, um Benutzer in Active Directory hinzufügen:

:: 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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X