The idea is to write and execute a repetitive loop controlled by a condition, not by a limit or number of files that are directly managed with FOR command. However, in this description we will use a very simple loop as example:
Code: Select all
set index=1
:While
if %index% gtr 10 goto EndWHile
echo Iteration number %index%
set /A index+=1
goto While
:EndWhile
Code: Select all
set index=1
:While
for /L %%z in () do (
if !index! gtr 10 goto EndWhile
echo Iteration number !index!
set /A index+=1
)
:EndWhile
Code: Select all
set index=1
:While
cmd /V:ON /Q /C WhileLoop
:EndWHile
Code: Select all
for /L %%z in () do (
if !index! gtr 10 exit
echo Iteration number !index!
set /A index+=1
)
We can include the While-body commands in the same Batch file and execute it with a special parameter (ie: "While") that indicate to execute the While-body instead of the original program, and an additional parameter to identify the While-body via its label. The While-body must be placed in a position that does not interfere with the original program; if we want to place the While-body in a visible position, it must be skipped when the original program run:
Code: Select all
@echo off
setlocal EnableDelayedExpansion
rem While dispatcher
if "%1" equ "While" goto %2
rem Original program
rem . . . .
rem Skip the While-body
goto EndWhile
:WhileBody
for /L %%z in () do (
if !index! gtr 10 exit
echo Iteration number !index!
set /A index+=1
)
:EndWhile
rem Execute the While
set index=1
cmd /Q /C %0 While WhileBody
We may improve this solution via Batch variables that aid to write clearer code. Also, we can reorder the IF inside the FOR /L in a way that allows the While condition be placed after the %While% auxiliary variable in a standard way:
Code: Select all
@echo off
setlocal EnableDelayedExpansion
rem While dispatcher
if "%1" equ "While" goto %2
rem Define auxiliary While variables
set While=for /L %%? in () do if
set Do=(
set EndWhile=) else exit
set RunWhile=cmd /Q /C "%~F0" While
rem Original program
rem . . . .
rem Skip the While-body
goto :EndWhile
:WhileBody
%While% !index! leq 10 %do%
echo Iteration number !index!
set /A index+=1
%EndWhile%
:EndWhile
rem Execute the While
set index=1
%RunWhile% WhileBody
This method works executing the Batch file twice: the first time in normal way with %1 not equal "While" (when the While-body is skipped), and the second nested time with %1 equal "While" (when the While-body is executed). We may include this condition in the same %While%-%EndWhile% macro pair inserting an additional IF, but in this case the optional variable that define the ERRORLEVEL value returned by the While-body can not be included. We may choose a standard variable name for this purpose (ie: "WhileResult") and include it in %EndWhile% macro. This way, it is no longer necessary to skip the While-body and the While can be put in the place it will be executed in an entirely standard way:
Code: Select all
@echo off
setlocal EnableDelayedExpansion
rem Define auxiliary While variables
set While=if "%1" equ "While" ( for /L %%? in () do if
set Do=(
set EndWhile=) else exit ^^!WhileResult^^! ) else cmd /Q /C "%~F0" While
rem While dispatcher
if "%1" equ "While" goto %2
rem Original program
rem . . . .
rem A standard While
set index=1
:WhileBody
%While% !index! leq 10 %do%
echo Iteration number !index!
set /A index+=1
%EndWhile% WhileBody
In Conclusion, to use a While in a Batch file:
1- Start your program with the first eight lines of the example program above (until the IF of While dispatcher).
2- Put a :label before the While and start it using %While% condition %Do% format. The condition is a standard IF command condition.
3- Close the While with %EndWhile% label using the same label before the %While%.
4- If you want the While returns a numeric result, assign it to WhileResult variable inside the While-body and retrieve it via %errorlevel% value after the %EndWhile%.
Remember that the values of variables modified inside the While must be retrieved via Delayed !variable! Expansion, but that this is not needed in SET /A command calculations, and that Delayed Expansion must be Enabled before execute the While; otherwise it is necessary to include /V:ON switch in the execution of cmd.exe in the EndWhile macro.
A small problem previous method have is that a While can not be nested inside another one. This problem may be solved differentiating %While% macro execution for each nested While via the %2 parameter, as shown in the program below. In this case, to use nested Whiles in a Batch file, modify previous steps this way:
1- Start your program with the first eight lines of the example program below.
2- Insert set WhileBody=label command followed by the :label and %While% condition %Do%.
3- Close the While with just %EndWhile%.
The example program below have two Whiles nested two levels deep; the nested While return a numeric result to the nesting one.
Code: Select all
@echo off
setlocal EnableDelayedExpansion
rem Define auxiliary While variables
set While=if %1-%2 equ While-^^!WhileBody^^! ( for /L %%? in () do if
set Do=(
set EndWhile=) else exit ^^!WhileResult^^! ) else cmd /Q /C "%~F0" While ^^!WhileBody^^!
rem While dispatcher
if "%1" equ "While" goto %2
set outer=10
set WhileBody=OuterLoop
:OuterLoop
%While% !outer! leq 100 %do%
set /A inner=1, WhileResult=0
set WhileBody=InnerLoop
:InnerLoop
%While% !inner! leq !outer! %do%
set /A WhileResult+=inner, inner+=1
%EndWhile%
set iterative=!errorlevel!
set /A calculated=(outer+1^)*outer/2
echo Summation of 1..!outer!: Iterative method=!iterative!, Calculated result=!calculated!
set /A outer+=10
%EndWhile%
Code: Select all
Summation of 1..10: Iterative method=55, Calculated result=55
Summation of 1..20: Iterative method=210, Calculated result=210
Summation of 1..30: Iterative method=465, Calculated result=465
Summation of 1..40: Iterative method=820, Calculated result=820
Summation of 1..50: Iterative method=1275, Calculated result=1275
Summation of 1..60: Iterative method=1830, Calculated result=1830
Summation of 1..70: Iterative method=2485, Calculated result=2485
Summation of 1..80: Iterative method=3240, Calculated result=3240
Summation of 1..90: Iterative method=4095, Calculated result=4095
Summation of 1..100: Iterative method=5050, Calculated result=5050
Antonio