FOR loop syntax

June 3, 2009 at 17:16:15
Specs: Windows XP
I'm working on a moderately complex batch
file. The original requirement was a way to do
a remote backup for a user who works from
home to ensure we have copies of his latest
work. After some quick poking around, I
decided that I could generate a pretty good
automated differential backup using a batch
file that would output commands to a text file
and call it with FTP. Simple, does the job,
and all stuff I had handy and was familiar with.
Best of all, I could automate it as a scheduled
event and take the human element out of the
equation entirely.

The issue I ran into was that the commandline
XP FTP client wasn't able to handle subfolders
like I was used to in XCOPY - it would dump
everything from the entire tree into one root
folder, and I happen to know he repeats
filenames.

I used some reasonably tricky string parsing
and loops to get the batch file to identify each
subfolder, from left to right, in the file's
location, and add a mkdir and cd line for each
one to the FTP script, as well as keep track of
how deep it gets so it can send an appropriate
number of "cd .." lines after the file gets MPUT
to the server.

The next problem I ran into was my admittedly
low-tech solution to generating a list of files - I
used a "DIR /s /a:a /b" command, output it to
a text file, and read it back into a variable with
a SET command. After the file was copied, I
flipped the archive switch, and looped. The
copied file would no longer show up on the list
and the next iteration caught the next file.

This worked well enough with my 25-file test
directory, but became a huge liability when I
tried it on an existing backup directory from a
local source - since the batch had to search
through over 1,500 files, once per file...I let it
run for five hours before I canceled it. It would
have worked eventually, but it clearly isn't fast
enough.

Someone pointed out to me that I could use a
FOR loop to read the DIR output into memory,
and save myself the recursive directory
hunting. It seems like a solid move, but I'm
having a hell of a time getting it to run.
Currently, it will only run once, and process
the second line. Anybody know what's wrong
with my FOR loop syntax here?


FOR /F "DELIMS==" %%I IN ('DIR /s /a:a /b') DO (SET FOLDER=%%~pI
SET RAWFILE=%%I
echo Searching for new and changed files...
echo Processing: %%I / !RAWFILE!
IF /I "!LASTFOLDER!"=="!FOLDER!" GOTO COPY
:up_folder
if not !FOLDER_COUNT! equ 0 (	echo cd ..>>ftp.txt
				set /a FOLDER_COUNT="!FOLDER_COUNT!-1"
				goto up_folder  )
IF /I "!FOLDER!"=="!HOME!" GOTO COPY	
echo IF "!FOLDER!"="!HOME!" GOTO COPY	
REM At this point, we know that FOLDER is not a duplicate of
REM the last cycle, and it is not the current directory.
CALL SET FOLDER=!FOLDER:%HOME%=!
REM At this point, FOLDER should be only the subdirectory, eg. Testing\
SET TARGET_FOLDER=!FOLDER!
SET SET_FOLDER=""
SET DIR_COUNT_TOTAL=0
:parse_folder
if "!TARGET_FOLDER!"=="" goto end_parse
echo Testing !TARGET_FOLDER!
IF "!TARGET_FOLDER:~-1!"=="\" SET SET_FOLDER=!TARGET_FOLDER!
IF "!TARGET_FOLDER:~-1!"=="\"  	SET DIR_COUNT=1
IF NOT "!TARGET_FOLDER:~-1!"=="\" SET /a DIR_COUNT="%DIR_COUNT%+1"
set TARGET_FOLDER=%TARGET_FOLDER:~0,-1%
goto parse_folder
:end_parse
set /a FOLDER_COUNT=!FOLDER_COUNT!+1
echo mkdir "!SET_FOLDER:~0,-1!">>ftp.txt
echo cd "!SET_FOLDER:~0,-1!">>ftp.txt
REM The DIR_COUNT variable iterates during each letter shaved after the folder
REM detects.  By shaving the sourcename by that much, the properly truncated
REM sourcename can be fed back to the folder parsing loop.
SET /A DIR_COUNT_TOTAL=!DIR_COUNT!+!DIR_COUNT_TOTAL!
CALL SET TARGET_FOLDER=%%FOLDER:~%DIR_COUNT_TOTAL%%%
IF "!TARGET_FOLDER!"=="" goto COPY
goto parse_folder
:COPY
REM This should be the copy procedure that is called once there is no folder 
REM manipulation to be done.
ECHO BEGINNING FILE COPY OF %RAWFILE%
echo mput "%RAWFILE%">>ftp.txt
attrib -a "%RAWFILE%"
Echo File added: %RAWFILE%
Set LASTFILE=%RAWFILE%
)
ECHO QUIT>>FTP.TXT
ECHO BACKUP COMPLETE!


See More: FOR loop syntax

Report •


#1
June 4, 2009 at 03:11:52
I did not walk through your quite cumbersome script, but at first glance I notice you use GOTO statements to jump to labels INSIDE the FOR loop. That is not allowed as it disrupts the nominal control flow. You can issue a GOTO inside a loop just to refer to an EXTERNAL label so leaving the instructions block.

So even by scripting you are forced to strictly follow the rules of "structured proggramming" (i.e. "GOTOless programming"). Challenging but not impoddible.

Good work.


Report •
Related Solutions


Ask Question