WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Samples From Users

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

Script to Synchronize Remote Directory with Local Directory

Keywords:    

Synchronize your remote file directory with your local directory. Great for updating web pages on a remote host. Compares each file and uploads if local copy is newer. This procedure has two pieces:
  1. SyncUpload.wbt: synchronizes remote ftp directory (and all subdirectories) with local files in current directory. Will not delete remote files nor transfer files to local machine (one way). I suspect it will fail if the remote directories don't exist.
    Released to the public domain by Rik Blok , 1997.

  2. ParseURL.WBT: parses a URL of the form protocol://userid:password@host/path returning the variables protocol, userid, password, host, path Uses a trick to distinguish between absolute and relative paths: /path is absolute (returns "/path") /~/path is relative (returns "path"). The "~" is used to identify the user's root path.

SyncUpload.WBT

; SyncUpload.wbt - synchronizes remote ftp directory (and all subdirectories)
;	with local files in current directory.	Will not delete remote files nor 
;	transfer files to local machine (one way).	I suspect it will fail if the 
;	remote directories don't exist.
;       Released to the public domain by Rik Blok , 1997.
WinTitle("","SyncUpload")

; initialize
AddExtender("WWWSK34I.DLL")
AsAscii="html htm txt ps"         ; file formats to transfer in ASCII mode
lib="C:\My Documents\WinBatch\Library\"

; parse command-line
Call("%lib%ParseURL.wbt",param1)
If host==""             Then host=AskLine("SyncUpload","Host:")
If userid==""   Then userid=AskLine("SyncUpload","UserID:")
If password=="" Then password=AskPassword("SyncUpload","Password:")

; connect
BoxOpen("SyncUpload","Connecting to %host%...")
ftp=ftpOpen(host,userid,password,"",1)
Drop(password)
If !IsNumber(ftp)
        BoxText(StrCat("Error connecting to ",host,@CRLF,ftp))
        GoTo Bye
EndIf

; change directories
If path!=""
        BoxText("Changing remote directory...")
        msg = ftpChDir(ftp,path)
        If msg != ""
                BoxText(StrCat("Error changing directory.",@CRLF,msg))
                GoTo Bye
        EndIf
EndIf

; build tree lists
GoSub rBuildTree
GoSub lBuildTree

; compare file timestamps and transfer if necessary
Transferred=ItemInsert("Transferred:",-1,"",@TAB)
Failed=ItemInsert("Failed:",-1,"",@TAB)
msg=StrCat("Comparing files...",@CRLF)
BoxText(msg)
While ItemCount(lFileList,@TAB) > 0
        msg=StrCat(msg,"|")
        BoxText(msg)
        lFilename=ItemExtract(1,lFileList,@TAB)
        lStamp=ItemExtract(2,lFileList,@TAB)
        GoSub GetrFilename
        rIndex=ItemLocate(rFilename,rFileList,@TAB)
        If rIndex == 0          ; if no remote file then upload
                ToUpload= @TRUE
        Else                            ; or if local file newer then upload
                rStamp=ItemExtract(rIndex+1,rFileList,@TAB)
                ToUpload = (TimeDiffSecs(lStamp,rStamp) > 0)
        EndIf
        If ToUpload
                If ItemLocate(FileExtension(lFilename),AsAscii," ") Then        mode="A"
                Else                                                                                                            mode="B"
                err=ftpPut(ftp,lFilename,rFilename,mode)
                Drop(mode)
                If err==""
                        rFileList=ItemRemove(rIndex,rFileList,@TAB)
                        rFileList=ItemRemove(rIndex,rFileList,@TAB)
                        Transferred=ItemInsert(StrCat("    ",lFilename),-1,Transferred,@TAB)
                Else
                        Failed=ItemInsert(StrCat("    ",lFilename),-1,Failed,@TAB)
                EndIf
        Else
                rFileList=ItemRemove(rIndex,rFileList,@TAB)
                rFileList=ItemRemove(rIndex,rFileList,@TAB)
        EndIf
        lFileList=ItemRemove(1,lFileList,@TAB)
        lFileList=ItemRemove(1,lFileList,@TAB)
EndWhile
Summary=""
If ItemCount(Transferred,@TAB)>1 Then Summary=Transferred
If ItemCount(Failed,@TAB)>1 Then Summary=StrCat(Summary,Failed)
Drop(Transferred,Failed)

; message if files not transferred
;If ItemCount(rFileList,@TAB) > 0
;        rFileList = ItemInsert("Error transferring files:",1,rFileList,@TAB)
;        AskItemList("SyncUpload",rFileList,@TAB,@unsorted,@single)
;EndIf

GoTo Bye
Exit

:GetrFilename
; Converts lFilename (local DOS) to rFilename (remote Unix)
        rFilename = StrReplace(lFilename,"\","/")
Return

:lBuildTree
; builds a directory tree of all files in the local path with timestamps
; Output:
;       lFileList       - list of files and timestamps
;
        BoxText("Building local file list...")
        lDir=""
        lDirList=""
        lFileList=""
        
        While @TRUE
                ; process path, add to local file and dir lists
                lDirTemp=DirItemize(StrCat(lDir,"*.*"))
                lFileTemp=FileItemize(StrCat(lDir,"*.*"))
                For i=1 To ItemCount(lDirTemp,@TAB)
                        lDirList=ItemInsert(StrCat(lDir,ItemExtract(i,lDirTemp,@TAB)),-1,lDirList,@TAB)
                Next
                For i=1 To ItemCount(lFileTemp,@TAB)
                        lFileList=ItemInsert(StrCat(lDir,ItemExtract(i,lFileTemp,@TAB)),-1,lFileList,@TAB)
                        lFileList=ItemInsert(FileYmdHms(StrCat(lDir,ItemExtract(i,lFileTemp,@TAB))),-1,lFileList,@TAB)
                Next
                Drop(i,lDirTemp,lFileTemp)

                ; if no more subdirectories then return
                If ItemCount(lDirList,@TAB)==0 Then Break
                ; else go to next subdirectory
                lDir = StrCat(ItemExtract(1,lDirList,@TAB),"\")
                lDirList = ItemRemove(1,lDirList,@TAB)
        EndWhile
        Drop(lDirList,lDir)
Return

:rBuildTree
; builds a directory tree of all files on the remote system with timestamps.
; Input:
;       ftp             - ftp connection handle
; Output:
;       rFileList - list of files and timestamps
;
        msg=StrCat("Building remote file list...",@CRLF)
        BoxText(msg)
        rDir=""
        rDirList=""
        rFileList=""
        flist="SyncUpload.tmp"
        
        While @TRUE
                ; build current directory list
                list=ftpList(ftp,rDir,flist)
                If list !=""
                        Message("SyncUpload","Error retrieving directory %rDir%")
                        GoTo Bye
                EndIf
                Drop(list)

                ; process file, add to remote file and dir lists
                h = FileOpen(flist,"READ")
                line = FileRead(h)      ; strip header
                While @TRUE
                        msg=StrCat(msg,"|")
                        BoxText(msg)
                        line = FileRead(h)
                        If line=="*EOF*" Then Break
                        GoSub ParseLine
                        If IsDir        ; if dir then add to dir list
                                rDirList=ItemInsert(StrCat(rDir,Name),-1,rDirList,@TAB)
                        Else            ; if file then add to file list
                                rFileList=ItemInsert(StrCat(rDir,Name,@TAB,Stamp),-1,rFileList,@TAB)
                        EndIf
                EndWhile
                FileClose(h)
                Drop(h,line,IsDir,Name,Stamp)
        
                ; if no more subdirectories then return
                If ItemCount(rDirList,@TAB)==0 Then Break
                ; else go to next subdirectory
                rDir = StrCat(ItemExtract(1,rDirList,@TAB),"/")
                rDirList = ItemRemove(1,rDirList,@TAB)
        EndWhile
        FileDelete(flist)
        Drop(flist,rDirList,rDir)
Return

:ParseLine
; parses a line from the current listing.
; Input:
;       line
; Output:
;       IsDir=@TRUE/@FALSE
;       Name=
;       Stamp=YY:MM:DD:HH:MM:SS

        ; parse into param1...param9
        ParseData(line)
        ; must be at least 9 parameters
        If param0 < 9 
                Message("SyncUpload",StrCat("Error parsing directory at line",@CRLF,line))
                GoTo Bye
        EndIf
        
        ; check if directory
        If StrSub(line,1,1)=="d" Then   IsDir=@TRUE
        Else                                                    IsDir=@FALSE
        
        ; get name 
        If param0 == 9          ; if only 9 params then just retrieve from param9
                Name = param9
        Else                            ; if more then spaces in filename
                ; guess starting position of filename.
                ; Try to avoid errors you might get if you had a strange filename like
                ; filename = "drwx------   2 blok     public       512 Jan  5  1995"
                pos=StrIndex(line,param1,  1,@FwdScan)+StrLen(param1)
                pos=StrIndex(line,param2,pos,@FwdScan)+StrLen(param2)
                pos=StrIndex(line,param3,pos,@FwdScan)+StrLen(param3)
                pos=StrIndex(line,param4,pos,@FwdScan)+StrLen(param4)
                pos=StrIndex(line,param5,pos,@FwdScan)+StrLen(param5)
                pos=StrIndex(line,param6,pos,@FwdScan)+StrLen(param6)
                pos=StrIndex(line,param7,pos,@FwdScan)+StrLen(param7)
                pos=StrIndex(line,param8,pos,@FwdScan)+StrLen(param8)
                Name = StrSub(line,StrIndex(line,param9,pos,@FwdScan),-1)
                Drop(pos)
        EndIf
        
        ; get date
        MM=ItemLocate(param6,"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"," ")
        DD=param7
        If StrScan(param8,":",0,@FWDSCAN)==0    ; no time, must be year
                YY=param8                                               ; actually YYYY
                Hms="00:00:00"
        Else                                                            ; time, no year
                YY=ItemExtract(1,TimeYmdHms(),":")
                Hms=StrCat(param8,":00")
        EndIf
        Stamp=StrCat(YY,":",MM,":",DD,":",Hms)
        Drop(YY,MM,DD,Hms)
Return

:Bye
        BoxText("Disconnecting...")
        ftpClose(ftp)
        BoxShut()
        If IsDefined(Summary)
                If Summary != "" Then AskItemList("SyncUpload",Summary,@TAB,@unsorted,@single)
                Drop(Summary)
        EndIf
        Drop(ftp)
Exit

ParseURL.wbt

; ParseURL.wbt - parses a URL of the form protocol://userid:password@host/path 
;       returning the variables protocol, userid, password, host, path
;       Uses a trick to distinguish between absolute and relative paths:
;               /path is absolute (returns "/path")
;               /~/path is relative (returns "path").
;       The "~" is used to identify the user's root path.
WinTitle("","ParseURL")

; error trapping
If param0==0
	protocol=""
	userid=""
	password=""
	host=""
	path=""
	Return
EndIf
s=param1

; extract protocol
i=StrIndex(s,"://",0,@FWDSCAN)
If i>0
	protocol=StrSub(s,1,i-1)
	s=StrSub(s,i+3,-1)
Else
	protocol=""
EndIf

; extract userid and password
i=StrIndex(s,"@",0,@FWDSCAN)
If i>0
	ss=StrSub(s,1,i-1)
	j=StrIndex(ss,":",0,@FWDSCAN)
	If j>0
		userid=StrSub(ss,1,j-1)
		password=StrSub(ss,j,-1)
	Else
		userid=ss
		password=""
	EndIf
	Drop(j,ss)
	s=StrSub(s,i+1,-1)
Else
	userid=""
	password=""
EndIf

; extract host and path
i=StrIndex(s,"/",0,@FWDSCAN)
If i>0
	host=StrSub(s,1,i-1)
	path=StrSub(s,i,-1)
	; if relative path then removing leading "/~/"
	If StrSub(path,1,3)=="/~/" Then path=StrSub(path,4,-1)
Else
	host=s
	path=""
EndIf
Drop(i,s)

Return

Article ID:   W12674
Filename:   Synchronize Remote Directory with Local Directory.txt
File Created: 2001:03:01:15:06:06
Last Updated: 2001:03:01:15:06:06