.BAT break out of multiple nested loop, after fini

2019-01-20 20:23发布

问题:

I know breaking out of a nested loop is fairly easy, however, I'm not sure how to do it when I'm working with multiple lists of servers. Here's the scenario:

Goal: Search for sessions on a server matching a specific user ID, and also kill any disconnected sessions found

Problem: I have multiple lists of farms. I want to cycle through the lists until I find the users session, and then stop when that list is finished (not stop when the session is cleared, they may have multiple sessions in the farm).

Farmlist1.txt farmlist2.txt farmlist3.txt

If the session is found in farmlist2.txt, I want to FINISH searching in that list, but don't continue to farmlist3.txt.

Here's what I have so far, and it works like a charm. (Optimizations welcomed)

@echo off
echoCitrix Session Reset
echo.
echo This will look for a specific userID AND kill disconnected sessions on     all servers!
set /p userid=User ID of the user: 
for %%a in (q:\scripts\1common\citrixlists\*.txt) do (
for /f "tokens=*" %%l in (%%a) do (
ping %%l -n 1 | find /i "TTL=" > nul 
if errorlevel 1 (
echo server %%l down or out of Load
) else (
echo Looking for %username% and killing disconnected sessions on %%l

for /f "tokens=3" %%b in ('qwinsta *tcp /server:%%l ^| find /i "%userid%"') do echo %%b | rwinsta %%b /server:%%l && echo SESSION FOR %userid% KILLED ON %%l

for /f "tokens=2" %%i IN ('qwinsta /server:%%l ^| find /i "disc"') DO (
if %%i gtr 0 (
rwinsta %%i /server:%%l && echo Disconnected sessions terminated
)

)

)

)

)   

回答1:

I do not exactly understand what you are trying to accomplish, but I do understand how to break out of nested for loops (or any other nested parenthesised blocks of code). So let me elaborate on that.

Breaking a single for loop is simple: put goto :STOP into the loop and the label :STOP in the line following the loop structure. The example below breaks the loop depending on its loop counter value:

@echo off
for /L %%I in (0,1,5) do (
    if %%I GTR 3 (
        echo Break!
        goto :STOP
    )
    echo %%I
)
:STOP

Although the loop is specified to count up to 5, the output is:

0
1
2
3
Break!

Note that the loop actually completes the counting internally, but no more commands are executed. You can easily reproduce that when you increase the end value 5 to a huge number like 1000000.


But now let us concentrate on nested loops (two in each example):

  1. The following code snippet breaks both loops upon a certain condition is met:

    @echo off
    for %%J in (Aa Bb Cc) do (
        for /L %%I in (0,1,5) do (
            if "%%~J"=="Bb" if %%I GTR 3 (
                echo Break!
                goto :STOP
            )
            echo %%J-%%I
        )
    )
    :STOP
    

    The output is:

    Aa-0
    Aa-1
    Aa-2
    Aa-3
    Aa-4
    Aa-5
    Bb-0
    Bb-1
    Bb-2
    Bb-3
    Break!
    

    As you can see, execution of the loop construct is interrupted immediately at a certain point.

  2. The batch file here breaks the outer loop when the a certain condition in the inner loop is met. The result of the check is transferred to the outer loop using a variable FLAG:

    @echo off
    set "FLAG="
    for %%J in (Aa Bb Cc) do (
        for /L %%I in (0,1,5) do (
            if "%%~J"=="Bb" if %%I GTR 3 (
                echo Break!
                set "FLAG=#"
            )
            echo %%~J-%%I
        )
        if defined FLAG goto :STOP
    )
    :STOP
    

    The output is:

    Aa-0
    Aa-1
    Aa-2
    Aa-3
    Aa-4
    Aa-5
    Bb-0
    Bb-1
    Bb-2
    Bb-3
    Break!
    Bb-4
    Break!
    Bb-5
    

    You will notice that the inner loop finishes execution before the outer one is broken.

  3. The script below breaks the inner loop when a certain condition is net. To not break the outer loop, a sub-routine holding the inner loop and being called (call) from the outer one is required to hide the code block context of the outer loop from the goto break-up method:

    @echo off
    for %%J in (Aa Bb Cc) do (
        call :SUB "%%~J"
    )
    goto :EOF
    
    :SUB
    for /L %%I in (0,1,5) do (
        if "%~1"=="Bb" if %%I GTR 3 (
            echo Break!
            goto :STOP
        )
        echo %~1-%%I
    )
    :STOP
    

    The output is:

    Aa-0
    Aa-1
    Aa-2
    Aa-3
    Aa-4
    Aa-5
    Bb-0
    Bb-1
    Bb-2
    Bb-3
    Break!
    Cc-0
    Cc-1
    Cc-2
    Cc-3
    Cc-4
    Cc-5
    

    Here the outer loop finishes its execution without being affected by the broken inner one.


I hope one of the (last two) examples suits the requirements for your script.