1.

Solve : Advance For Loop?

Answer»

I am WORKING on a script to copy files to remote systems.  I am stuck where I check a text file to see if this system has had the folder copied or not.  If it has, then I need to skip the IF statements and just advance the loop to check for the next system....I have put in italics the portion I am having problems with...

echo off
for /f "tokens=*" %%i in (\\dclib3\tech\maintscript\copyscript\systems.txt) do (
        
      
      FINDSTR /C:%%i \\dclib3\tech\maintscript\copyscript\log\copyscript.txt
                IF %errorlevel%==0 then advance the loop to check for new system      
      echo %%i>>\\dclib3\tech\maintscript\copyscript\log\copyscript.txt

      IF EXIST \\%%i\C$\windows\nul (
      echo d|xcopy \\dclib3\tech\maintscript\MaintXP \\%%i\C$\ /Y /S /E
                echo Y|CACLS "\\%%i\C$\maintscript" /P everyone:F )

      IF EXIST \\%%i\C$\winnt\nul (
      echo d|xcopy \\dclib3\tech\maintscript\MaintXP \\%%i\C$\ /Y /S /E
      echo Y|CACLS "\\%%i\C$\maintscript" /P everyone:F )
                  
      )

Errorlevel cannot be checked as a numeric and the implied comparison is equal or greater than.

Code: [Select]echo off
for /f "tokens=*" %%i in (\\dclib3\tech\maintscript\copyscript\systems.txt) do (
     FINDSTR /C:%%i \\dclib3\tech\maintscript\copyscript\log\copyscript.txt
     IF errorlevel 1 (      
        echo %%i>>\\dclib3\tech\maintscript\copyscript\log\copyscript.txt
 
        IF EXIST \\%%i\C$\windows\nul (
          echo d|xcopy \\dclib3\tech\maintscript\MaintXP \\%%i\C$\ /Y /S /E
          echo Y|CACLS "\\%%i\C$\maintscript" /P everyone:F )
 
        IF EXIST \\%%i\C$\winnt\nul (
          echo d|xcopy \\dclib3\tech\maintscript\MaintXP \\%%i\C$\ /Y /S /E
          echo Y|CACLS "\\%%i\C$\maintscript" /P everyone:F )
        )        
     )

The theory here is that if errorlevel is 1 or greater (not found from the FINDSTR) then all your logic gets executed. If errorlevel is zero (found in the FINDSTR) then all your logic is skipped and the loop gets executed again with a new variable value. I tested this for syntax; I'll leave it to you for the logic portion.


PS. Generally I don't encourage the use of administrative shares (C$) due to  potential security issues. But hey, that's just me.What about more complex logic?

ASSUME that MyFile.txt is a list formatted as follows:
SourceDrive:\SourcePath SourceFileName TargetDrive:\TargetPath

Example:
C:\Temp File1.txt C:\Target1
C:\Foo File2.txt C:\Target2
etc.

Let's say I want to validate each element, and skip to the next iteration of the loop if any of that validation fails.

Code: [Select]ECHO OFF
FOR /F "tokens=1-3" %%a IN (MyFile.txt) DO (

    SET SourceDir=%%a
    SET SourceFile=%%b
    SET TargetDir=%%c

:ValidateSourceDir
    IF NOT EXIST !SourceDir! (
        ECHO Invalid Source Directory !SourceDir!
        REM Loop to the next iteration
    ) ELSE (
      ECHO Source Directory !SourceDir! Validated
    )

:ValidateSourceFile
    IF NOT EXIST !SourceDir!\!SourceFile! (
        ECHO Invalid Source File !SourceDir!\!SourceFile!
        REM Loop to the next iteration
    ) ELSE (
      ECHO Source File !SourceDir!\!SourceFile! Validated
    )

:ValidateTargetDir
    IF NOT EXIST !TargetDir! (
        ECHO Invalid Target Directory !TargetDir!
        REM Loop to the next iteration
    ) ELSE (
      ECHO Target Directory !TargetDir! Validated
    )

:NowDoSomeOtherStuff
    XCOPY !SourceDir!\!SourceFile! !TargetDir!

)

The :Labels are there simply for readability.  Constructing this with nested, all-or-nothing execution is ugly, and a pain, especially as additional logic is needed.

The following looks like it should do the trick, but it fails with, "The syntax of the command is incorrect.":

Code: [Select]ECHO OFF
FOR /F "tokens=1-3" %%a IN (MyFile.txt) DO (

    SET SourceDir=%%a
    SET SourceFile=%%b
    SET TargetDir=%%c

:ValidateSourceDir
    IF NOT EXIST !SourceDir! (
        ECHO Invalid Source Directory !SourceDir!
        REM Loop to the next iteration
        GOTO NextLoop

    ) ELSE (
      ECHO Source Directory !SourceDir! Validated
    )

:ValidateSourceFile
    IF NOT EXIST !SourceDir!\!SourceFile! (
        ECHO Invalid Source File !SourceDir!\!SourceFile!
        REM Loop to the next iteration
        GOTO NextLoop
    ) ELSE (
      ECHO Source File !SourceDir!\!SourceFile! Validated
    )

:ValidateTargetDir
    IF NOT EXIST !TargetDir! (
        ECHO Invalid Target Directory !TargetDir!
        REM Loop to the next iteration
        GOTO NextLoop
    ) ELSE (
      ECHO Target Directory !TargetDir! Validated
    )

:NowDoSomeOtherStuff
    XCOPY !SourceDir!\!SourceFile! !TargetDir!

:NextLoop

)

I do not get the "incorrect syntax" error if I add some place-holder statement after the :NextLoop tag, like this...
Code: [Select]:NextLoop
ECHO. > NUL

...BUT, if any iteration fails -- for example, with "Invalid Source File C:\Temp\NoSuchFile.txt," the loop terminates.

How can I loop to the next iteration of a FOR loop?

btw, I have been a fan of this site for a long time, and this is my first post!  SORRY about resurrecting an old post, but that serves two purposes: It shows that I've searched for a solution first, and it best illustrates the problem.  Thank you for your (past and future) assistance!  I hope I can contribute.

EDIT: I know, I can validate path and file name in one step, with "IF EXIST !SourceDir!\!SourceFile!," but I wanted to illustrate a multi-stage validation process.
I suspect that the goto instructions are preempting the return address of the for loop. By fixing the syntax error, I created my own until I moved the :NextLoop outside the for loop which of course changed the entire logic of your file.

Going back to my KISS roots, I give you this for your consideration:

Code: [Select]ECHO OFF
FOR /F "tokens=1-3" %%a IN (MyFile.txt) DO (
SET SourceDir=%%a
    SET SourceFile=%%b
    SET TargetDir=%%c
    set valid=Y

:ValidateSourceDir
    IF NOT EXIST !SourceDir! (
        ECHO Invalid Source Directory !SourceDir!
        set valid=N
)
:ValidateSourceFile   
    IF NOT EXIST !SourceDir!\!SourceFile! (
        ECHO Invalid Source File !SourceDir!\!SourceFile!
        set valid=N
)
:ValidateTargetDir
    IF NOT EXIST !TargetDir! (
        ECHO Invalid Target Directory !TargetDir!
        set valid=N
    )
   
if valid==Y XCOPY !SourceDir!\!SourceFile! !TargetDir!
)   

Your processor is probably fast enough not to notice the extra microseconds needed to process all the CONDITIONS before deciding to run XCOPY


 KISS indeed.  MUCH appreciated!



Discussion

No Comment Found