Tom's Guide | Tom's Hardware | Tom's Games
![]() |
![]() |
![]() |
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!

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.

![]() |
![]() |
![]() |

This post is quite old and has been locked from receiving new replies. Please create a new posting instead.
| Ads by Google |