Here's a version that supports multiple source folders. The "reporting functions" are more spread about in this version so if you only need to back up one folder, use the code in first post as it's easier to customise.
Code: Select all
Macro R(t)
MessageRequester("Archive program reporting...",t,0)
EndMacro
Macro EnsureThisEnd(t,endd)
If endd<>""
If Right(t,Len(endd)) <> endd
t+endd
EndIf
EndIf
EndMacro
Macro EnsureThisNotEnd(t,endd)
If Right(t,Len(endd)) = endd
;snipped.s = Len(t)-Len(endd)
;t = Left(t,snipped)
t = Left(t,Len(t)-Len(endd))
EndIf
EndMacro
Macro EnsureThisStart(t,start)
If start<>""
If Left(t,Len(start)) <> start
t = start+t
EndIf
EndIf
EndMacro
Macro EnsureThisNotStart(t,start)
If Left(t,Len(start)) = start
t = Mid(t,Len(start)+1,Len(t))
EndIf
EndMacro
Macro IsDrivePath(path)
(Len(path)=3 And Right(path,2)=":\")
EndMacro
Procedure.b EnsureFolder(folder.s)
If FileSize(folder)=-2
ProcedureReturn #True
Else
ProcedureReturn CreateDirectory(folder)
EndIf
EndProcedure
Procedure.f Defeat(a.f,b.f)
If a<b
ProcedureReturn a
Else
ProcedureReturn b
EndIf
EndProcedure
Procedure.s GetFieldsFromStart(str.s,level.l,d.s)
fields = CountString(str,d)
accum.s
For a = 1 To Defeat(level,fields)
accum+StringField(str,a,d)+d
Next a
ProcedureReturn accum
EndProcedure
Procedure.b EnsureFolderPath(path.s)
If FileSize(path)=-2
ProcedureReturn #True
EndIf
EnsureThisEnd(path,"\")
shortpath.s
levels = CountString(path,"\")
If levels>1
For f = 1 To levels
shortpath = GetFieldsFromStart(path,f,"\")
If IsDrivePath(shortpath)
success+1
Continue
EndIf
success+EnsureFolder(shortpath)
Next f
EndIf
If success=levels
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
Procedure.b AppendToFile(filename.s,t.s)
;R("APPEND TO FILE."+c13+c13+filename+c13+c13+t)
c10.s = Chr(10)
c13.s = Chr(13)
If Not EnsureFolderPath(GetPathPart(filename)) : R("CAN'T CREATE FOLDER PATH: "+filename) : ProcedureReturn #False : EndIf
t = RemoveString(t,c10)
t = ReplaceString(t,c13,c13+c10)
If FileSize(filename)>-1
;R("FILE EXISTS")
file = OpenFile(#PB_Any,filename)
If file
loaf = Lof(file)
If loaf
FileSeek(file,loaf-1)
If ReadAsciiCharacter(file)<>10
EnsureThisStart(t,c13+c10)
EndIf
FileSeek(file,loaf)
EndIf
WriteString(file,t)
CloseFile(file)
ProcedureReturn #True
EndIf
Else
f = CreateFile(#PB_Any,filename)
If f
WriteStringN(f,t)
CloseFile(f)
ProcedureReturn #True
EndIf
EndIf
EndProcedure
Procedure.s CorrectPluralate(num.i,singular.s,plural.s,space.b,includenumeral.b)
If num=1 And num>0
t.s = singular
Else
t = plural
EndIf
If space
t = " "+t
EndIf
If includenumeral
t = Str(num)+t
EndIf
ProcedureReturn t
EndProcedure
Procedure.s MonthName(num.b)
Select num
Case 1
ProcedureReturn "January"
Case 2
ProcedureReturn "February"
Case 3
ProcedureReturn "March"
Case 4
ProcedureReturn "April"
Case 5
ProcedureReturn "May"
Case 6
ProcedureReturn "June"
Case 7
ProcedureReturn "July"
Case 8
ProcedureReturn "August"
Case 9
ProcedureReturn "September"
Case 10
ProcedureReturn "October"
Case 11
ProcedureReturn "November"
Case 12
ProcedureReturn "December"
EndSelect
EndProcedure
Procedure.s Hour24To12(hour.i)
suffix.s
Select hour
Case 0 To 11, 24
suffix="am"
If hour=24
hour-12
EndIf
Case 12 To 23
suffix="pm"
If hour>12
hour-12
EndIf
EndSelect
ProcedureReturn Str(hour)+"|"+suffix+"|"
EndProcedure
Procedure.s ToCoolDate(dl,date.b,time.b)
datestring.s
timestring.s
;DT_LongToDT(datelong,@dt.dtsplit)
month$ = Left(MonthName(Month(dl)),3)
a$ = Hour24To12(Hour(dl))
domini$ = StringField(a$,2,"|")
hour.i = Val(StringField(a$,1,"|"))
If time
timestring = RSet(Str(hour),2,"0")+":"+RSet(Str(Minute(dl)),2,"0")+domini$
EndIf
If date
datestring = RSet(Str(Day(dl)),2,"0")+"/"+month$+"/"+Str(Year(dl))
EndIf
info.s
If date
info + datestring
If time
info+" @ "
EndIf
EndIf
If time
info + timestring
EndIf
; date @ time
ProcedureReturn info
EndProcedure
Structure FolderEntry
name.s
is_folder.b
EndStructure
Procedure.i List_GetFilesInFolder(folder.s,recursive.b,List farr.FolderEntry())
EnsureThisEnd(folder,"\")
thisfilename.s
;R("FOLDER: "+folder)
d = ExamineDirectory(#PB_Any,folder,"")
If d
While NextDirectoryEntry(d)
thisfilename = DirectoryEntryName(d)
If RemoveString(thisfilename,".")
;Debug "thisfilename: "+thisfilename
Select DirectoryEntryType(d)
Case #PB_DirectoryEntry_File
AddElement(farr())
farr()\name = folder+thisfilename
itemsinthisfolder+1
Case #PB_DirectoryEntry_Directory
AddElement(farr())
farr()\name = folder+thisfilename
farr()\is_folder = #True
If recursive
itemsinthisfolder + List_GetFilesInFolder(folder+thisfilename,#True,farr())
EndIf
EndSelect
EndIf
Wend
FinishDirectory(d)
EndIf
;R("itemsinthisfolder: "+Str(itemsinthisfolder))
ProcedureReturn itemsinthisfolder
EndProcedure
Procedure.s ReplacePath(fn.s,path1.s,path2.s)
EnsureThisNotStart(fn,path1)
fn = path2+fn
ProcedureReturn fn
EndProcedure
Macro EnsureNoExtraneousFiles(fn,copyfol,origfol)
ForEach fn()
;R("FN: "+fn())
copyfn.s = fn()\name
twinfn.s = ReplacePath(copyfn,copyfol,origfol)
If fn()\is_folder
If FileSize(twinfn)<>-2
;R("OBSOLETE DIRECTORY IN ARCHIVE FOLDER:"+c13+copyfn)
DeleteDirectory(copyfn,"*.*",#PB_FileSystem_Recursive|#PB_FileSystem_Force)
bk()\obsolete_folders+1
EndIf
Else
If FileSize(twinfn)<0
;R("OBSOLETE FILE IN ARCHIVE FOLDER:"+c13+copyfn)
DeleteFile(copyfn)
bk()\obsolete_files+1
EndIf
EndIf
Next
EndMacro
Macro UpdatePresentFiles(fn,copyfol,origfol)
ForEach fn()
;R("FN: "+fn())
If fn()\is_folder : Continue : EndIf
copyfn.s = fn()\name
origfn.s = ReplacePath(copyfn,copyfol,origfol)
doit.b = #False
If FileSize(origfn)<0 And FileSize(copyfn)>-1
; file doesn't exist in master folder
DeleteFile(copyfn)
bk()\obsolete_files+1
Continue
EndIf
If FileSize(copyfn) <> FileSize(origfn)
doit=#True
Else
If GetFileDate(origfn,#PB_Date_Modified) > GetFileDate(copyfn,#PB_Date_Modified)
doit=#True
EndIf
EndIf
If doit
DeleteFile(copyfn)
CopyFile(origfn,copyfn)
bk()\updated_files+1
EndIf
Next
EndMacro
Macro AddMissingFiles(origfilename,origfol,copyfol)
ForEach origfilename()
;R("FN: "+fn())
origfn.s = origfilename()\name
copyfn.s = ReplacePath(origfn,origfol,copyfol)
If origfilename()\is_folder
If FileSize(copyfn)<>-2
; folder doesn't exist in archive folder
;EnsureFolderPath(GetPathPart(copyfn))
;CopyFile(origfn,copyfn)
CreateDirectory(copyfn)
bk()\new_folders+1
EndIf
Else
If FileSize(copyfn)=-1
; file doesn't exist in archive folder
EnsureFolderPath(GetPathPart(copyfn))
CopyFile(origfn,copyfn)
bk()\new_files+1
EndIf
EndIf
Next
EndMacro
Structure CopyDestination
locale.s
obsolete_folders.i
obsolete_files.i
updated_folders.i
updated_files.i
new_folders.i
new_files.i
EndStructure
Global NewList fa.s()
;-------- SET FOLDERS TO BE BACKED UP
AddElement(fa()) : fa() = "C:\family photos\"
AddElement(fa()) : fa() = "C:\diary entries\"
Global NewList bk.CopyDestination()
;-------- SET BACKUP FOLDERS...
; for maximum safety, these should be on different hard drives
AddElement(bk()) : bk()\locale = "E:\BACKUPS\"
AddElement(bk()) : bk()\locale = "P:\BACKUPS\"
AddElement(bk()) : bk()\locale = "X:\BACKUPS\"
;-------- SET REPORT FILE...
archivereportfile.s = "C:\archive-info.txt"
c13.s = Chr(13)
NewList origfilename.FolderEntry()
NewList copyfn.FolderEntry()
ForEach bk()
EnsureThisEnd(bk()\locale,"\")
Next
AppendToFile(archivereportfile,c13+c13+"--------------------------------------------------"+c13+ToCoolDate(Date(),#True,#True)+c13)
ForEach fa()
masterlocale.s = fa()
If masterlocale="" Or FileSize(masterlocale)<>-2
R("ERROR. Master locale "+Chr(34)+masterlocale+Chr(34)+" not found.")
Continue
EndIf
EnsureThisEnd(masterlocale,"\")
ClearList(origfilename())
List_GetFilesInFolder(masterlocale,#True,origfilename())
If Not ListSize(origfilename())
R("No files in master locale.")
Continue
EndIf
dashed_masterlocale.s = masterlocale
dashed_masterlocale = RemoveString(dashed_masterlocale,":")
dashed_masterlocale = ReplaceString(dashed_masterlocale,"\","-")
EnsureThisNotEnd(dashed_masterlocale,"-")
dashed_masterlocale+"\"
ClearList(copyfn())
;- DO IT...
ForEach bk()
copylocale.s = bk()\locale+dashed_masterlocale
;R("COPYING FROM:"+c13+origlocale+c13+"TO:"+c13+copylocale)
EnsureFolderPath(copylocale)
ClearList(copyfn())
items = List_GetFilesInFolder(copylocale,#True,copyfn())
EnsureNoExtraneousFiles(copyfn,copylocale,masterlocale)
UpdatePresentFiles(copyfn,copylocale,masterlocale)
AddMissingFiles(origfilename,masterlocale,copylocale)
Next ; next copying locale
;- FORM REPORT...
;arcinfo.s = "-------------------------"+c13
arcinfo.s = c13
arcinfo + " MASTER: "+masterlocale+c13
ForEach bk()
;arcinfo + " COPY: "+bk_locale() + c13
arcinfo + "ARCHIVE: "+bk()\locale + c13
changesum = bk()\obsolete_files+bk()\obsolete_folders+bk()\new_files+bk()\new_folders+bk()\updated_files+bk()\updated_folders
If changesum
If bk()\obsolete_folders
arcinfo + " "+CorrectPluralate(bk()\obsolete_folders,"obsolete folder","obsolete folders",#True,#True)+" deleted"+c13
EndIf
If bk()\updated_folders
arcinfo + " "+CorrectPluralate(bk()\updated_folders,"folder","folders",#True,#True)+" updated"+c13
EndIf
If bk()\new_folders
arcinfo + " "+CorrectPluralate(bk()\new_folders,"new folder","new folders",#True,#True)+" added"+c13
EndIf
If bk()\obsolete_files
arcinfo + " "+CorrectPluralate(bk()\obsolete_files,"obsolete file","obsolete files",#True,#True)+" deleted"+c13
EndIf
If bk()\updated_files
arcinfo + " "+CorrectPluralate(bk()\updated_files,"file","files",#True,#True)+" updated"+c13
EndIf
If bk()\new_files
arcinfo + " "+CorrectPluralate(bk()\new_files,"new file","new files",#True,#True)+" added"+c13
EndIf
Else
arcinfo + " [no changes]"+c13
EndIf
Next
AppendToFile(archivereportfile,arcinfo)
Next
RunProgram(archivereportfile)