0
    set checker=0

for %%a in (%namelist%) do (
:startLoop
    findstr "completed" %%a_Logs.txt
    IF ERRORLEVEL 1 (
        IF %checker%==120 (
            set checker=0
            goto endLoop
        )
        set /a checker=%checker%+1
        @ping 127.0.0.1 -n 1 -w 1000 > nul
        findstr "ERROR" %%a_Logs.txt
        IF ERRORLEVEL 1 (
            echo Waiting 1 second before rechecking (Max 2 mins)
            echo time elapsed %checker% seconds
            echo.
            goto startLoop
        )
        findstr "ERROR" %%a_Logs.txt
        IF NOT ERRORLEVEL 1 (
            echo ERROR: %%a Error found
            goto endLoop
        )
    )
    findstr "completed" %%a_Logs.txt
    IF NOT ERRORLEVEL 1 (
        echo %%a completed
    )
:endLoop
)

The above piece of code is to do the following:

  1. Parse the variable namelist(where the contents are separated by spaces)
  2. Check if "completed" is present in the %%a_Logs.txt file
  3. If it is present, then iteration over, If it is not, then check for the string "ERROR" in same file
  4. If ERROR is present, then output ERROR MSG and end iteration
  5. If ERROR is not found, keep rechecking for the next 120 seconds before ending iteration

I keep getting the following output

FINDSTR: Cannot open %a_Logs.txt

rainman_s
  • 1,088
  • 1
  • 8
  • 19

2 Answers2

4

You are attempting to GOTO a label within a FOR loop - that simply doesn't work. The moment a FOR loop executes GOTO, the loop is terminated, and the FOR context is lost. So your %%a FOR variable is no longer defined. A similar issue happens with IF statements, as described at (Windows batch) Goto within if block behaves very strangely.

You also have a problem when you attempt to expand %checker% within the same parenthesized code block that sets the value. That expansion occurs at parse time, and the entire block is parsed at once. So the value you see will always be the value that existed before the block was entered. The solution is to enable delayed expansion and use !checker! instead of %checker%.

Personally, I would probably make significant changes to your code. But I believe the following minimal changes can make your code work, assuming there are no other bugs:

  • enable delayed expansion
  • Move your DO loop code to a routine outside of the loop, and then have the loop CALL that routine with %%a as a parameter. CALL does not break the loop.
  • Substitute %1 for %%a in the routine
  • Substitute exit /b for goto endLoop. Also put exit /b at end of the routine
  • Make sure the code does not fall into the routine when the FOR loop finishes. I used a GOTO after the FOR loop
  • Substitute !checker! for %checker%
  • EDIT -The ) in the ECHO statement must be escaped

Here is the modified code (untested)

setlocal enableDelayedExpansion
set checker=0
for %%a in (%namelist%) do call :startLoop %%a
goto continue

:startLoop
findstr "completed" %1_Logs.txt
IF ERRORLEVEL 1 (
    IF !checker!==120 (
        set checker=0
        exit /b
    )
    set /a checker=checker+1
    @ping 127.0.0.1 -n 1 -w 1000 > nul
    findstr "ERROR" %1_Logs.txt
    IF ERRORLEVEL 1 (
        echo Waiting 1 second before rechecking (Max 2 mins^)
        echo time elapsed !checker! seconds
        echo.
        goto startLoop
    )
    findstr "ERROR" %1_Logs.txt
    IF NOT ERRORLEVEL 1 (
        echo ERROR: %1 Error found
        exit /b
    )
)
findstr "completed" %1_Logs.txt
IF NOT ERRORLEVEL 1 (
    echo %1 completed
)
exit /b

:continue
Community
  • 1
  • 1
dbenham
  • 127,446
  • 28
  • 251
  • 390
  • One more error, if you use a variable instead of a file in a for loop, you need to enclose it in double quotes. I can't give you an example because i'm on my phone. – BDM Feb 27 '13 at 10:09
  • 1
    Oh, and you need to escape the parenthesis within the echo command. – BDM Feb 27 '13 at 10:13
  • @ProfPickle - Good catch with the unescaped `)`, I've updated the answer. But you are wrong about the quotes being needed in the FOR statement. This is a simple FOR loop that iterates space delimited tokens within the IN() clause, not FOR /F parsing a string value. Quotes around the variable would break the functionality, as the entire contents would then be treated as one token. – dbenham Feb 27 '13 at 12:23
  • Thanks a lot guys! I just realized my mistake in using goto in a for loop. You're solution is brilliant. And I've tested it, and it works. – rainman_s Feb 27 '13 at 15:51
  • @Varun_S - If you have gotten a satisfactory answer, you should accept the answer by clicking the check mark near the upper left corner. That action lets others know the question has been answered, it awards you 2 reputation points, and awards the answerer 15 rep points. Only 1 answer may be accepted per question. Once you reach 15 rep points, you will gain the ability to up vote any answer you find useful, even answers to other people's questions. An up vote awards 10 points to the answerer. – dbenham Feb 27 '13 at 16:46
2

I think the labels inside your for loop are messing it up. I just tried it moving the contents of the loop into a separate "subroutine" and that gets rid of the error you mention.

Try this:

set checker=0

for %%a in (foo bar baz) do (
    call :loop %%a
)
goto :eof

:loop
set basename=%1
:startLoop
findstr "completed" %basename%_Logs.txt
IF ERRORLEVEL 1 (
    IF %checker%==120 (
        set checker=0
        goto endLoop
    )
    set /a checker=%checker%+1
    @ping 127.0.0.1 -n 1 -w 1000 > nul
    findstr "ERROR" %basename%_Logs.txt
    IF ERRORLEVEL 1 (
        echo Waiting 1 second before rechecking (Max 2 mins)
        echo time elapsed %checker% seconds
        echo.
        goto startLoop
    )
    findstr "ERROR" %basename%_Logs.txt
    IF NOT ERRORLEVEL 1 (
        echo ERROR: %basename% Error found
        goto endLoop
    )
)
findstr "completed" %basename%_Logs.txt
IF NOT ERRORLEVEL 1 (
    echo %basename% completed
)
:endLoop
goto :eof
Nate Hekman
  • 6,507
  • 27
  • 30
  • A couple minutes late, but +1 anyway :-) There are additional problems with the OP's code. See [my answer](http://stackoverflow.com/a/15101655/1012053). – dbenham Feb 26 '13 at 23:54
  • Too funny--I kept coming back to this question throughout the day and being interrupted. When I finally finished my answer and hit Submit, yours had come through a minute before. :-) Your answer is more complete anyway, so I +1'd it too. – Nate Hekman Feb 27 '13 at 03:49