Aacini
The documentation of EXIT command given at https://ss64.com/nt/exit.html indicate that a FOR command placed in a subroutine can be terminated with EXIT /B command. However, this not works if the loop is a FOR /L one. The only way to break a FOR /L is with plain EXIT command, and the way to avoid the termination of the whole cmd.exe session is invoking the "subroutine" via cmd /C "%~F0" :sub trick instead of CALL, and start the batch file with: IF "%~1" EQU :sub GOTO sub
Last edited by Aacini (19 Nov 2015 15:31)
----------------------------
#20 Nov 2015 11:38
Simon Sheppard
It works for me, heres a simple example of exit /b with FOR /L
Code: Select all
@echo off
setlocal
call :sub
echo all done
goto:eof
:sub
For /l %%G in (1,1,5) do (echo %%G & exit /b)
Echo end of the subroutine we will never get here
goto :eof
In PowerShell we have a proper break-loop command https://ss64.com/ps/break.html
----------------------------
#20 Nov 2015 12:47
npocmaka
Try this (with small numbers you wont see the difference):
Code: Select all
@echo off
setlocal
call :sub
echo all done
goto:eof
:sub
For /l %%G in (1,1,10000000) do (echo %%G & exit /b)
Echo end of the subroutine we will never get here
goto :eof

----------------------------
#20 Nov 2015 13:08
jeb
Or see the cause with this sample
Code: Select all
echo ON
For /l %%G in (1,1,3) do (
echo %%G
exit /b
)
Code: Select all
C:\temp>For /L %G in (1 1 3) do (
echo %G
exit /b
)
C:\temp>(
echo 1
exit /b
)
1
C:\temp>(
echo 2
)
C:\temp>(
echo 3
)
Currently I'don't understand why the EXIT/B isn't displayed by the ECHO ON.
Btw.
This also affects the (GOTO) 2>NUL technic (I'm not able to find the Dostips topic)
As the FOR /L loop can't be immediatly stopped without EXIT, the stack analyzer can hang at this point.
But the effects are strange here, as it's still possible to discover the call stack but the loop will still iterate later.
Last edited by jeb (20 Nov 2015 13:18)
----------------------------
#20 Nov 2015 16:16
Aacini
The real problem with this point appear when we want to break an infinite loop, but I didn't wanted to present this example before because it could cause discussions that have no relation with the core point of this problem:
Code: Select all
@echo off
setlocal EnableDelayedExpansion
call :sub
echo all done
goto:eof
:sub
set i=0
For /l %%G in () do (
set /A i+=1
echo !i!
if !i! equ 5 exit /b
)
Echo end of the subroutine we will never get here
goto :eof
This problem may also affect other situations with loops with few iterations; see: https://stackoverflow.com/questions/337 ... batch-file In that code the loop could be changed by a normal "(1,1,10)" one and the program still give wrong results...
Last edited by Aacini (20 Nov 2015 16:31)
----------------------------
#20 Nov 2015 19:20
jeb
I can't confirm this, just tested with W7x64. I changed the loop to (1,1,10)Aacini wrote:
If the EXIT /B would break the FOR /L the control would return to the main program after 5 iterations, but this never happens...
... In that code the loop could be changed by a normal "(1,1,10)" one and the program still give wrong results...
Code: Select all
1
2
3
4
5
all done
Last edited by jeb (20 Nov 2015 19:22)
----------------------------
#20 Nov 2015 20:28
Simon Sheppard
Great explanations!
I've added a paragraph about this to https://ss64.com/nt/exit.html
Thanks all
----------------------------
#21 Nov 2015 03:37
Aacini
@jeb: I think you mixed up two different paragraphs of my reply. When I wrote "In that code" I meant the one posted at the link placed immediately before that phrase. "That code" contain this segment:jeb wrote:
I can't confirm this, just tested with W7x64. I changed the loop to (1,1,10)Aacini wrote:
If the EXIT /B would break the FOR /L the control would return to the main program after 5 iterations, but this never happens...
... In that code the loop could be changed by a normal "(1,1,10)" one and the program still give wrong results...
The point about unbreakable infinite loops is still valid.Code: Select all
1 2 3 4 5 all done
Code: Select all
REM -- NOTE: Infinite loop, breaks out when root directory is reached --
REM -- or makefile is found --
for /L %%n in (1,0,10) do (