[windows] While loop in batch

Here is what I want, inside the BACKUPDIR, I want to execute cscript /nologo c:\deletefile.vbs %BACKUPDIR% until number of files inside the folder is greater than 21(countfiles holds it). Here is my 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%
)

This question is related to windows batch-file for-loop while-loop

The answer is


set /a countfiles-=%countfiles%

This will set countfiles to 0. I think you want to decrease it by 1, so use this instead:

set /a countfiles-=1

I'm not sure if the for loop will work, better try something like this:

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

A while loop can be simulated in cmd.exe with:

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

For example, the following script:

    @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

outputs:

0
1
2
3
4
5

For your particular case, I would start with the following. Your initial description was a little confusing. I'm assuming you want to delete files in that directory until there's 20 or less:

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

@echo off

set countfiles=10

:loop

set /a countfiles -= 1

echo hi

if %countfiles% GTR 0 goto loop

pause

on the first "set countfiles" the 10 you see is the amount it will loop the echo hi is the thing you want to loop

...i'm 5 years late


I have a trick for doing this!

I came up with this method because while on the CLI, it's not possible to use the methods provided in the other answers here and it had always bugged me.

I call this the "Do Until Break" or "Infinite" Loop:

Basic Example

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 )

This is truly an infinite loop!

This is useful for monitoring something in a CMD window, and allows you to use CTRL+C to break it when you're done.

Want to Have a counter?

Either use SET /A OR You can modify the FOR /L Loop to do the counting and still be infinite (Note, BOTH of these methods have a 32bit integer overflow)

SET /A Method:

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  )

Native FOR /L Counter:

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  )

Counting Sets of 4294967295 and Showing Current Value of 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 )

However, what if:

  • You're interested in reviewing the output of the monitor, and concerned that I will pass the 9999 line buffer limit before I check it after it has completed.
  • You'd like to take some additional actions once the Thing I am monitoring is finished.

For this, I determined how to use a couple methods to break the FOR Loop prematurely effectively turning it into a "DO WHILE" or "DO UNTIL" Loop, which is otherwise sorely lacking in CMD.

NOTE: Most of the time a loop will continue to iterate past the condition you checked for, often this is a wanted behavior, but not in our case.

Turn the "infinite Loop" into a "DO WHILE" / "DO UNTIL" Loop

UPDATE: Due to wanting to use this code in CMD Scripts (and have them persist!) as well as CLI, and on thinking if there might be a "more Correct" method to achieve this I recommend using the New method!

New Method (Can be used inside CMD Scripts without exiting the 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
)

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

Original Method (Will work on CLI just fine, but will kill a 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

Older Post Stuff

Through chance I had hit upon some ways to exit loops prematurely that did not close the CMD prompt when trying to do other things which gave me this Idea.

NOTE:

While ECHO.>&3 >NUL had worked for me in some scenarios, I have played with this off and on over the years and found that DIR >&0 >NUL was much more consistent.

I am re-writing this answer from here forward to use that method instead as I recently found the old note to myself to use this method instead.

Edited Post with better Method Follows:

DIR >&0 >NUL

The >NUL is optional, I just prefer not to have it output the error.

I prefer to match inLine when possible, as you can see in this sanitized example of a Command I use to monitor LUN Migrations on our 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 )

Also, I have another method I found in that note to myself which I just re-tested to confirm works just as well at the CLI as the other method.

Apparently, when I first posted here I posted an older iteration I was playing with instead of the two newer ones which work better:

In this method, we use EXIT /B to exit the For Loop, but we don't want to exit the CLI so we wrap it in a CMD session:

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)

Because the loop itself happens in the CMD session, we can use EXIT /B to exit the iteration of the loop without losing our CMD Session, and without waiting for the loop to complete, much the same as with the other method.

I would go so far as to say that this method is likely the "intended" method for the sort of scenario where you want to break a for loop at the CLI, as using CMD session is also the only way to get Delayed expansion working at the CLI for your loops, and the behavior and such behavior is clearly an intended workflow to leave a CMD session.

IE: Microsoft clearly made an intentional effort to have CMD Exit /B For loops behave this way, while the "Intended" way of doing this, as my other method, relies on having accidentally created just the right error to kick you out of the loop without letting the loop finish processing, which I only happenstantially discovered, and seems to only reliably work when using the DIR command which is fairly strange.

So that said, I think it's probably a better practice to use Method 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)

Although I suspect Method 1 is going to be slightly faster:

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

And in either case, both should allow DO-While loops as you need for your purposes.


It was very useful for me i have used in the following way to add user in 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

Examples related to windows

"Permission Denied" trying to run Python on Windows 10 A fatal error occurred while creating a TLS client credential. The internal error state is 10013 How to install OpenJDK 11 on Windows? I can't install pyaudio on Windows? How to solve "error: Microsoft Visual C++ 14.0 is required."? git clone: Authentication failed for <URL> How to avoid the "Windows Defender SmartScreen prevented an unrecognized app from starting warning" XCOPY: Overwrite all without prompt in BATCH Laravel 5 show ErrorException file_put_contents failed to open stream: No such file or directory how to open Jupyter notebook in chrome on windows Tensorflow import error: No module named 'tensorflow'

Examples related to batch-file

'ls' is not recognized as an internal or external command, operable program or batch file '' is not recognized as an internal or external command, operable program or batch file XCOPY: Overwrite all without prompt in BATCH CanĀ“t run .bat file under windows 10 Execute a batch file on a remote PC using a batch file on local PC Windows batch - concatenate multiple text files into one How do I create a shortcut via command-line in Windows? Getting Error:JRE_HOME variable is not defined correctly when trying to run startup.bat of Apache-Tomcat Curl not recognized as an internal or external command, operable program or batch file Best way to script remote SSH commands in Batch (Windows)

Examples related to for-loop

List append() in for loop Prime numbers between 1 to 100 in C Programming Language Get current index from foreach loop how to loop through each row of dataFrame in pyspark TypeScript for ... of with index / key? Is there a way in Pandas to use previous row value in dataframe.apply when previous value is also calculated in the apply? Python for and if on one line R for loop skip to next iteration ifelse How to append rows in a pandas dataframe in a for loop? What is the difference between ( for... in ) and ( for... of ) statements?

Examples related to while-loop

While, Do While, For loops in Assembly Language (emu8086) MySQL Insert with While Loop Python loop to run for certain amount of seconds How to break a while loop from an if condition inside the while loop? How to find sum of several integers input by user using do/while, While statement or For statement Python: How to keep repeating a program until a specific input is obtained? Creating multiple objects with different names in a loop to store in an array list ORA-06502: PL/SQL: numeric or value error: character string buffer too small How to break out of a loop in Bash? for or while loop to do something n times