In batch, I want to run something 10 times and then goto continue.
How would I do this?
Here's one approach:
#echo off
setlocal enabledelayedexpansion
echo before
set i=0
:loop1
echo something 10 times
set /a i+=1
if !i!==10 goto continue
goto loop1
:continue
echo after
exit /b 0
The easiest way to do this is a for /L loop.
for /L %%A in (1,1,10) do (
rem your code here
)
goto continue
The format for a for /L loop is (start,step,end), so (1,1,10) means start at 1 and count to 10 by 1s.
Related
Ive been trying to loop a batch file exactly 5 times using the set /a operation and so far no luck! Could someone help me?
#ECHO OFF
set loopCount=0
:loop
echo Checked %loopCount% times...
set /a loopCount=1+%loopCount%
if loopCount == 5 (goto exit) else (goto loop)
:exit
cls
echo Finished after %loopCount% times
pause >nul
Best of luck to whoever can help me
Here's a couple of examples to help you.
Using GoTo with a label:
#Set "loopCount=0"
:loop
#Set /A loopCount += 1
#Rem Some actual command goes here.
#Echo Checked %loopCount% times...
#If %loopCount% Lss 5 GoTo loop
#%SystemRoot%\System32\timeout.exe /T 2 /NoBreak 1>NUL
#ClS
#Echo Finished after being checked %loopCount% times.
#Pause 1>NUL
Alternatively, using a For /L looping mechanism:
#Set "maxCount=5"
#For /L %%G In (1,1,%maxCount%) Do #(
Rem Some actual command goes here.
Echo Checked %%G times...
)
#%SystemRoot%\System32\timeout.exe /T 2 /NoBreak 1>NUL
#ClS
#Echo Finished after being checked %maxCount% times.
#Pause 1>NUL
If you need to execute the entire batch script 5 times, the following method of storing an execution count in an alternate data stream of the script can be used:
#Echo off
more < "%~f0:Count" 2>&1 > nul && (
For /f "usebackq delims=" %%G in (`more ^< "%~f0:Count"`)Do Set /A Count=%%G+1
) || (
Set /A "Count+=1"
)
Echo(%Count% >"%~f0:Count"
:# Your script below
Echo(Script execution: %Count%
:# Terminate script execution after count reached
If %Count% EQU 5 (
Echo(0 >"%~f0:Count"
Exit /B
)
"%~f0"
#echo off
:start
set CTR=1
:loop
echo Lanz
set /a ctr=%CTR%+1
if ctr LEQ 5(
echo Lanz
) else goto loop
if ctr==5 goto finish
:finish
echo %CTR%
pause
cls
goto start
I just need help on this.
The instruction is that it needs to display the name five times in a loop statement form.
It's difficult because what my teacher gave me is a flowchart, I followed everything to the letter, it's not working. Help
Why not use a for loop?
#echo off
for /l %%a in (1,1,5) do (
echo Lanz
)
pause
If you want to stick with goto, it might look similar to this:
#echo off
set ctr=1
:loop
echo Lanz
set /a ctr=%ctr%+1
if %ctr% LEQ 5 goto loop
echo %ctr%
pause
There's no need for other labels and gotos: simple as do ... while
The following code runs a continuous loop, which increments the variable counter. When counter reaches 10, it should call the set_varibles routine, and then continue in the loop from the place set_variables was called. However, the goto does not work. What is wrong, and is there a better solution? Thanks
#echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
:set_variables
SET t=ooo
:my_loop
set /a counter=0
for /L %%n in (1,0,10) do (
echo !counter!
set /a counter=counter+1
if !counter! equ 10 (
echo now TEN
goto set_variables
)
)
#echo on
ENDLOCAL
CALL a subroutine (:label)
The following code runs a continuous loop, which increments the
variable counter. When counter reaches 10, it should call the
set_varibles routine, and then continue in the loop from the place
set_variables was called.
Exactly as proposed: echo now TEN and call :set_variables every tenth pass the endless loop.
#echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
call :set_variables
:my_loop
set /a counter=0
for /L %%n in (1,0,10) do (
echo !counter!
set /a counter=counter+1
set /a auxcounter=counter%%10
if !auxcounter! equ 0 (
echo now TEN
call :set_variables
)
)
#echo on
ENDLOCAL
#goto :eof
:set_variables
SET t=ooo
#goto :eof
Your main problem is not the goto command, but the for /l
While usually a goto command will cancel any block of code (code in parenthesis), for /l loops are a different beast. There are only two ways to leave a running for /l: an exit command (not exit /b unless the code is running in a command line context), or if the counter is greater than the end value.
Than means that the goto can not go out of the loop. It will cancel the execution of the code inside the do clause, but the loop will not be finished until the end value is reached, and your for loop
start step end
for /L %%n in ( 1, 0, 10 ) do ...
has a step value of 0 making it impossible to reach the end value.
The equivalent to your posted code could be
#echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
:set_variables
SET t=ooo
:my_loop
for /L %%n in (0,1,9) do (
echo %%n
set /a counter=%%n+1
rem ....
)
echo now TEN
goto set_variables
Isn't this what you want:
#echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
:set_variables
:my_loop
for /L %%n in (1,1,10) do (
echo %%n
if %%n equ 10 (
echo now TEN
SET t=ooo
)
)
goto my_loop
#echo on
ENDLOCAL
Using GOTO within parenthesis - including FOR and IF commands - will break their context.
Some things look odd in your script. Why have a continuous loop and then restart it when a counter reaches 10? Why not use "in (1,1,10)" like in Monacraft's answer?
Why does this tweaked version not do what you want?
#echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
set /a outer_counter=0
:set_variables
echo start of set_variables
SET t=ooo
:my_loop
set /a counter=0
for /L %%n in (1,1,10) do (
echo !counter!
set /a counter=counter+1
set /a outer_counter=outer_counter+1
if !counter! equ 10 (
echo now TEN
)
)
if !outer_counter! geq 100 goto after_loop
goto set_variables
:after_loop
echo FINISHED
#echo on
ENDLOCAL
pause
I hate when additional specifications are placed in comments instead of the question description, but this comment appeared below Monacraft's answer:
I want to re-run the routine which is called periodically within the loop.
Everytime the counter reaches a certain value, the routine must be called
and the counter variable reset.
So I think that the solution to all OP's requests is this:
#echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
call :set_variables
:my_loop
for /L %%n in (1,0,10) do (
echo !counter!
set /a counter=counter+1
if !counter! equ 10 (
echo now TEN
call :set_variables
)
)
No matter what is placed here, because a *continuous loop* NEVER ENDS!
#echo on
ENDLOCAL
:set_variables
SET t=ooo
set /a counter=0
exit /B
How do I loop a batch script only a certain amount of times (x10 or something)?
If the code was:
#echo off
:loop1
Start taskmgr.exe
Goto loop
:loop2
Start cmd.exe
goto loop2
How can loop loop1 and few times and go to loop2?
Any helpful answer would be appreciated :)
For a reason that i'm ignoring, the FOR command won't work for looping a specific label.
For example (I may be wrong):
#echo off
for /L %%a in (1,1,2) do (
goto loop
)
:loop
echo this won't loop for 2 times.
This will simply loop infinite times. So, I have found an alternative simple method to loop a label as many times as I want. To do this, I create a variable, like loop that will have an even bigger number every time the label repeats.
There is an example:
#echo off
set loop=0
:loop
echo hello world
set /a loop=%loop%+1
if "%loop%"=="2" goto next
goto loop
:next
echo This text will appear after repeating "hello world" for 2 times.
Output:
hello world
hello world
This text will appear after repeating "hello world" for 2 times.
Explanation:
set loop=0 sets the value of the variable loop at 0;
set /a loop=%loop%+1 adds 1 every time the label :loop is repeated.
if "%loop%"=="2" goto next tests if the variable loop is equal to 2 (so it was repeated for 2 times); if it's equal, it will go to the label :next, otherwise it will go to the label :loop.
if you open a command window and type FOR /? it will give you the command you are looking for.
FOR /L %variable IN (start,step,end) DO command [command-parameters]
The set is a sequence of numbers from start to end, by step amount.
So (1,1,5) would generate the sequence 1 2 3 4 5 and (5,-1,1) would
generate the sequence (5 4 3 2 1)
Here is an example:
#echo off
for /L %%a in (1,1,10) do (
Start taskmgr.exe
)
for /L %%a in (1,1,10) do (
Start cmd.exe
)
#echo off
set /a a=1
goto loop
:loop
echo looped %a% times so far
set /a a=%a%+1
if %a%=10 (
echo looped a total of %a% times
)
You can also use this command:
#echo off
for /l %%a in (1,1,10) do (
rem %%a is a variable and starts at a value of 1, steps by 1 and ends at a value of 10
start "Command Prompt #%%a Opened" cmd
rem eg Command Prompt #1 Opened
rem eg Command Prompt #2 Opened
rem etc
)
which opens Command Prompt with the title "Command Prompt #%%a Opened". rem is a command that you can use to write comments.
Try this:
#echo off
set loopvar=1
:repeat
if %loopvar% gtr 5 (goto :done) else (set /a loopvar=%loopvar%+1 && echo Loop && goto :repeat)
:done
Under :done, write the code you want it to do after the loop. Make sure to replace five with the number of times you want the loop to repeat.
For delay in the loop, try this:
#echo off
set loopvar=1
:repeatwithdelay
if %loopvar% gtr 5 (goto :done) else (set /a loopvar=%loopvar%+1 && timeout /T 1 >nul && echo Loop && goto :repeatwithdelay)
Hope it helped!
Why does this batch file never break out of the loop?
For /L %%f In (1,1,1000000) Do #If Not Exist %%f Goto :EOF
Shouldn't the Goto :EOF break out of the loop?
Edit:
I guess I should've asked more explicitly... how can I break out of the loop?
Based on Tim's second edit and this page you could do this:
#echo off
if "%1"=="loop" (
for /l %%f in (1,1,1000000) do (
echo %%f
if exist %%f exit
)
goto :eof
)
cmd /v:on /q /d /c "%0 loop"
echo done
This page suggests a way to use a goto inside a loop, it seems it does work, but it takes some time in a large loop. So internally it finishes the loop before the goto is executed.
You could simply use echo on and you will see that goto :eof or even exit /b doesn't work as expected.
The code inside of the loop isn't executed anymore, but the loop is expanded for all numbers to the end.
That's why it's so slow.
The only way to exit a FOR /L loop seems to be the variant of exit like the exsample of Wimmel, but this isn't very fast nor useful to access any results from the loop.
This shows 10 expansions, but none of them will be executed
echo on
for /l %%n in (1,1,10) do (
goto :eof
echo %%n
)
My answer
Use nested for loops to provide break points to the for /l loop.
for %%a in (0 1 2 3 4 5 6 7 8 9) do (
for %%b in (0 1 2 3 4 5 6 7 8 9) do (
for /l %%c in (1,1,10) do (
if not exist %%a%%b%%c goto :continue
)
)
)
:continue
Explanation
The code must be tweaked significantly to properly use the nested loops. For example, what is written will have leading zeros.
"Regular" for loops can be immediately broken out of with a simple goto command, where for /l loops cannot. This code's innermost for /l loop cannot be immediately broken, but an overall break point is present after every 10 iterations (as written). The innermost loop doesn't have to be 10 iterations -- you'll just have to account for the math properly if you choose to do 100 or 1000 or 2873 for that matter (if math even matters to the loop).
History
I found this question while trying to figure out why a certain script was running slowly. It turns out I used multiple loops with a traditional loop structure:
set cnt=1
:loop
if "%somecriteria%"=="finished" goto :continue
rem do some things here
set /a cnt += 1
goto :loop
:continue
echo the loop ran %cnt% times
This script file had become somewhat long and it was being run from a network drive. This type of loop file was called maybe 20 times and each time it would loop 50-100 times. The script file was taking too long to run. I had the bright idea of attempting to convert it to a for /l loop. The number of needed iterations is unknown, but less than 10000. My first attempt was this:
setlocal enabledelayedexpansion
set cnt=1
for /l %%a in (1,1,10000) do (
if "!somecriteria!"=="finished" goto :continue
rem do some things here
set /a cnt += 1
)
:continue
echo the loop ran %cnt% times
With echo on, I quickly found out that the for /l loop still did ... something ... without actually doing anything. It ran much faster, but still slower than I thought it could/should. Therefore I found this question and ended up with the nested loop idea presented above.
Side note
It turns out that the for /l loop can be sped up quite a bit by simply making sure it doesn't have any output. I was able to do this for a noticeable speed increase:
setlocal enabledelayedexpansion
set cnt=1
#for /l %%a in (1,1,10000) do #(
if "!somecriteria!"=="finished" goto :continue
rem do some things here
set /a cnt += 1
) > nul
:continue
echo the loop ran %cnt% times
you do not need a seperate batch file to exit a loop using exit /b if you are using call instead of goto like
call :loop
echo loop finished
goto :eof
:loop
FOR /L %%I IN (1,1,10) DO (
echo %%I
IF %%I==5 exit /b
)
in this case, the "exit /b" will exit the 'call' and continue from the line after 'call'
So the output is this:
1
2
3
4
5
loop finished
So I realize this is kind of old, but after much Googling, I couldn't find an answer I was happy with, so I came up with my own solution for breaking a FOR loop that immediately stops iteration, and thought I'd share it.
It requires the loop to be in a separate file, and exploits a bug in CMD error handling to immediately crash the batch processing of the loop file when redirecting the STDOUT of DIR to STDIN.
MainFile.cmd
ECHO Simple test demonstrating loop breaking.
ECHO.
CMD /C %~dp0\LOOP.cmd
ECHO.
ECHO After LOOP
PAUSE
LOOP.cmd
FOR /L %%A IN (1,1,10) DO (
ECHO %%A
IF %%A EQU 3 DIR >&0 2>NUL )
)
When run, this produces the following output. You'll notice that both iteration and execution of the loop stops when %A = 3.
:>MainFile.cmd
:>ECHO Simple test demonstrating loop breaking.
Simple test demonstrating loop breaking.
:>ECHO.
:>CMD /C Z:\LOOP.cmd
:>FOR /L %A IN (1 1 10) DO (
ECHO %A
IF %A EQU 3 DIR 1>&0 2>NUL
)
:>(
ECHO 1
IF 1 EQU 3 DIR 1>&0 2>NUL
)
1
:>(
ECHO 2
IF 2 EQU 3 DIR 1>&0 2>NUL
)
2
:>(
ECHO 3
IF 3 EQU 3 DIR 1>&0 2>NUL
)
3
:>ECHO.
:>ECHO After LOOP
After LOOP
:>PAUSE
Press any key to continue . . .
If you need to preserve a single variable from the loop, have the loop ECHO the result of the variable, and use a FOR /F loop in the MainFile.cmd to parse the output of the LOOP.cmd file.
Example (using the same LOOP.cmd file as above):
MainFile.cmd
#ECHO OFF
ECHO.
ECHO Simple test demonstrating loop breaking.
ECHO.
FOR /F "delims=" %%L IN ('CMD /C %~dp0\LOOP.cmd') DO SET VARIABLE=%%L
ECHO After LOOP
ECHO.
ECHO %VARIABLE%
ECHO.
PAUSE
Output:
:>MainFile.cmd
Simple test demonstrating loop breaking.
After LOOP
3
Press any key to continue . . .
If you need to preserve multiple variables, you'll need to redirect them to temporary files as shown below.
MainFile.cmd
#ECHO OFF
ECHO.
ECHO Simple test demonstrating loop breaking.
ECHO.
CMD /C %~dp0\LOOP.cmd
ECHO After LOOP
ECHO.
SET /P VARIABLE1=<%TEMP%\1
SET /P VARIABLE2=<%TEMP%\2
ECHO %VARIABLE1%
ECHO %VARIABLE2%
ECHO.
PAUSE
LOOP.cmd
#ECHO OFF
FOR /L %%A IN (1,1,10) DO (
IF %%A EQU 1 ECHO ONE >%TEMP%\1
IF %%A EQU 2 ECHO TWO >%TEMP%\2
IF %%A EQU 3 DIR >&0 2>NUL
)
Output:
:>MainFile.cmd
Simple test demonstrating loop breaking.
After LOOP
ONE
TWO
Press any key to continue . . .
I hope others find this useful for breaking loops that would otherwise take too long to exit due to continued iteration.
As jeb noted, the rest of the loop is skipped but evaluated, which makes the FOR solution too slow for this purpose. An alternative:
set F=1
:nextpart
if not exist "%F%" goto :EOF
echo %F%
set /a F=%F%+1
goto nextpart
You might need to use delayed expansion and call subroutines when using this in loops.
It is impossible to get out of a FOR /L before it completes all iterations.
I have debugged the execution of a FOR /L by the cmd.exe process.
Microsoft could document it better and save us all this effort.
Facts:
The loop is a simple while (TRUE) and the break only happens when the iteration limit is reached.
When an EXIT /b or a GOTO is encountered, no more commands are executed until the end of the iterations.
When an EXIT is encountered, the cmd.exe process is terminated.
Tests:
12 seconds
FOR /L %%G in (1,1,5000000) do (ECHO Only once & GOTO :EOF)
7 seconds
FOR /L %%G in (1,1,5000000) do (ECHO Only once & EXIT /b)
0 seconds, but this terminates the cmd.exe process
FOR /L %%G in (1,1,5000000) do (ECHO Only once & EXIT)
Assuming that the OP is invoking a batch file with cmd.exe, to properly break out of a for loop just goto a label;
Change this:
For /L %%f In (1,1,1000000) Do If Not Exist %%f Goto :EOF
To this:
For /L %%f In (1,1,1000000) Do If Not Exist %%f Goto:fileError
.. do something
.. then exit or do somethign else
:fileError
GOTO:EOF
Better still, add some error reporting:
set filename=
For /L %%f In (1,1,1000000) Do(
set filename=%%f
If Not Exist %%f set tempGoto:fileError
)
.. do something
.. then exit or do somethign else
:fileError
echo file does not exist '%filename%'
GOTO:EOF
I find this to be a helpful site about lesser known cmd.exe/DOS batch file functions and tricks: https://www.dostips.com/
Did a little research on this, it appears that you are looping from 1 to 2147483647, in increments of 1.
(1, 1, 2147483647): The firs number is the starting number, the next number is the step, and the last number is the end number.
Edited To Add
It appears that the loop runs to completion regardless of any test conditions. I tested
FOR /L %%F IN (1, 1, 5) DO SET %%F=6
And it ran very quickly.
Second Edit
Since this is the only line in the batch file, you might try the EXIT command:
FOR /L %%F IN (1, 1, 2147483647) DO #IF NOT EXIST %%F EXIT
However, this will also close the windows cmd prompt window.