Breaking out of FOR in batch

13,468

Solution 1

You are correct that a FOR /L loop "always" counts to completion. (Well, actually there are some drastic coding methods that can break it, but no need to go there)

However, even though the loop counts to completion, the DO clause is skipped once the GOTO FOUND statement has been executed. You can prove this to yourself by inserting echo testing %%a& in the front of your existing DO clause. You will see that no additional testing takes place once you have found your free port.

The FOR /L loop counts very fast (at least by batch standards), so I wouldn't worry about the extra counting. Now if your were counting 1 through 1 million, then I might worry. At 10 million I am definitely concerned.

I can simplify your existing logic a bit. You can combine the 2 FIND statements into a single FINDSTR using a regular expression.

for /L %%a in (8000,1,8100) do netstat /a /n | findstr /rc:"%%a.*LISTENING" || set tmp_freeport=%%a && goto found

I am no expert concerning IP addresses and ports, but I am concerned that your FIND logic may be inadequate to screen for used ports. I think looking for a colon before and a space after the port will make it more reliable. Also, I doubt you want to see the text of the used ports, so I redirected the FINDSTR output to nul.

for /L %%a in (8000,1,8100) do netstat /a /n | findstr /rc:":%%a .*LISTENING" >nul || set tmp_freeport=%%a && goto found

Note: GOTO :Label will immediately terminate all other forms of a FOR loop. Only the FOR /L variant continues to count after a GOTO.

Solution 2

You could just use IF and GOTO instead. Something like:

SET /A  a=8000

:loop

(Search and set variable here, use %a% instead of %%a, then GOTO found if found.)

SET /A a=a+1

IF %a% LEQ 8100 GOTO loop

:found
Share:
13,468
Niet the Dark Absol
Author by

Niet the Dark Absol

Need to remake this. In the meantime, check out my game!

Updated on June 25, 2022

Comments

  • Niet the Dark Absol
    Niet the Dark Absol almost 2 years

    My current line of batch code is:

    for /L %%a in (8000,1,8100) do netstat /a /n | find "%%a" | find "LISTENING" || set tmp_freeport=%%a && goto found
    

    The idea is to find a free port that will be used for listening, within the range of 8000-8100.

    Currently, I have port 8000 in use, so the script should go to 8001.

    After the loop, %tmp_freeport% is equal to 8001, as it should be, and its value is used later correctly.

    The problem is that the loop keeps running regardless. netstat is called to search for all 101 ports in the range, which is obviously inefficent and unwanted, because the search must complete before the script can continue.

    Can anyone tell me how to break out of a batch FOR loop?

    (Alternatively, if there's a better way of finding a free port, please see my somewhat-related question)

  • Niet the Dark Absol
    Niet the Dark Absol about 12 years
    Okay, so even though the commands are being listed when ECHO is on, they're not actually being executed? That's nice to know, and explains why the result is still 8001.