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:
- 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.
- 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