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

File Version and Dir Mgmt

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

TreeCopy Utility - A Smarter XCOPY

Keywords:    xcopy

Here's a handty utility that operates like XCOPY only with a bit more intelligence. Copies one subdirectory structure to another. optionally replaces newer files in the target with older files in the source, or leaves the newer ones untouched.

To Download a zip file with all of E.R.'s examples


;TREECOPY2.WBT    ;

 ;*****************************************************************************
; TREECOPY UTILITY  (TU)
; Written by E.Tippelt  100115.3301@compuserve.com
; Will do a winbatch xcopy function
; Uses the DSM.WBT code which handles single directory copies with additional
; code to extract the directory trees
; 2006/03/02 Z de Goris
; fixed up for @tab delimiters (orginal written in days of spaces)
;*****************************************************************************
:TU1
;Entry Parameters ; COMMENT OUT IF CALLED FROM ELSEWHERE
   If !IsDefined(Filetype) Then Filetype="*.*"
   If !IsDefined(DeleteTargetFiles) Then DeleteTargetFiles=0
   If !IsDefined(DowngradeTargetFiles) Then DowngradeTargetFiles=0
   If !IsDefined(SourceRoot) Then  SourceRoot=""
   If !IsDefined(TargetRoot) Then  TargetRoot=""
   SourceRoot=AskDirectory("GET SOURCE DIRECTORY","",SourceRoot,"",1|2)
   TargetRoot=AskDirectory("GET TARGET DIRECTORY","",TargetRoot,"",1|2)

If !DirExist(SourceRoot)
  Message("PARAMETER ERROR","Source Directory does not exist, Program Aborted")
  Return
EndIf

TargetDrive=StrCat(StrSub(TargetRoot,1,2),"\")     ;Get the target drive letter
level=0
treelist=""
treelist%level%=SourceRoot
:TU5
If treelist%level%==""
  Goto TU10        ;Got the directory list, now do something with it!
Else
  GoSub TU50
EndIf
Goto TU5

:TU10
;The variable TREELIST now contains a space delimited, fully pathed, list of
;all the source subdirectories, using the source directory as the starting point.

 ;This bit of code will save the directory list to a file, as it will be too
 ;long to display in a message box in most cases
 ;handle = fileopen("c:\dirlist.txt","write")
 ;filewrite(handle,treelist)
 ;fileclose(handle)

dr=ItemCount(treelist,@TAB)
 ;message("Number of Directories",dr)

 SourceDir=SourceRoot   ;do the root directories first
 TargetDir=TargetRoot
 GoSub dsm5     ;do the directory copy

;Now make sure that both SourceRoot and TargetRoot have a backslash on the end
;to cater for the situation where either source or target is something like c:
If StrSub(SourceRoot,StrLen(SourceRoot),1)!= "\" Then SourceRoot=StrCat(SourceRoot,"\")
If StrSub(TargetRoot,StrLen(TargetRoot),1)!= "\" Then TargetRoot=StrCat(TargetRoot,"\")
For k = 2 To dr
 SourceDir=ItemExtract(k,treelist,@TAB)
 TargetDir=StrReplace(SourceDir,SourceRoot,TargetRoot)
 GoSub dsm5     ;do the directory copy
Next k
Return  ;Go back to calling program
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;SUBROUTINES
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

;*****************************************************************************
;GET DIRECTORIES AT A GIVEN LEVEL IN THE TREE
;*****************************************************************************

:TU50
treelist=StrCat(treelist,@TAB,treelist%level%)
treelist=StrTrim(treelist) ;This will be the space delimited list of all the
                           ;directories in the tree

workinglevel=treelist%level%
treeno=ItemCount(workinglevel,@TAB)  ;get the number of entries in the current tree level
level=level+1
treelist%level%=""         ;get ready to generate the next level of the tree
For i=1 To treeno
 srcdir=ItemExtract(i,workinglevel,@TAB)
 GoSub TU60
 If PathedDirList!="" Then treelist%level%=StrCat(treelist%level%,@TAB,PathedDirList)
Next i
 treelist%level%=StrTrim(treelist%level%)
Return

;*****************************************************************************
;GET SUBDIRECTORIES AT A GIVEN LEVEL IN THE TREE
;*****************************************************************************
:TU60
;Entry parameters:
;SrcDir
;level
  slash=""
  length=StrLen(SrcDir)
  Last=StrSub(SrcDir,length,1)
  If last!="\" Then slash="\"
DirChange(SrcDir)
DirList=DirItemize("*.*")
DirNo=ItemCount(Dirlist,@TAB)      ;Count the entries in DirList
PathedDirList=""
If DirNo==0 Then Return
For j=1 To DirNo
  Dir=ItemExtract(j,DirList,@TAB)  ;Get each entry in the directory list
  Dir=StrCat(SrcDir,slash,Dir)
 If PathedDirList==""
    PathedDirList=Dir
 Else
    PathedDirList=StrCat(PathedDirList,@TAB,Dir)
 EndIf
Next j
Return                               ;Fully pathed list of subdirectories
                              ;at a given level in the tree
                                     ;Becomes the treelist%level% for the next level

;****************************************************************************
; Directory Synchronization Module (DSM)
; Written by E.Tippelt  100115.3301@compuserve.com
; Will synchronize the Source and Target directories
; Old files will be overwritten in the target
; Files not present in the source will be deleted in the target if required
;****************************************************************************
:DSM1
;Entry parameters:
;SourceDir="C:\windows"
;TargetDir="C:\test"
;Filetype="*.*"
;DeleteTargetFiles=0
;DowngradeTargetFiles=0
:DSM5                           ;Start Here
OrigDir=DirGet()                ;Save current Directory
:DSM10
If Filetype=="" Then Filetype="*.*"
SourceList=FileItemize("%SourceDir%\%Filetype%")
TargetList=FileItemize("%TargetDir%\%Filetype%")
SourceNo=ItemCount(Sourcelist,@TAB)      ;Count the entries in SourceList
DirChange(TargetDrive)
If !DirExist(TargetDir)
  DirMake(TargetDir)
  Goto DSM50
EndIf
TargetNo=ItemCount(TargetList,@TAB)      ;Count the entries in TargetList
If TargetNo==0 Then Goto DSM50
DirChange(TargetDir)
ErrorMode(@OFF)
FileAttrSet("*.*","rAsh")    ;Clear RSH/ Set A  target attributes for copy
                           ;in case there are existing files with set attribs
ErrorMode(@CANCEL)
For i=1 To SourceNo
  Item=ItemExtract(i,SourceList,@TAB)        ;Get each entry in the source list
  Pos=ItemLocate(Item,TargetList,@TAB)       ;See if present in target list
  If pos !=0
    TargetList=ItemRemove(pos,TargetList,@TAB) ;if present, delete the item
    TargetNo=TargetNo-1
    If TargetNo==0 Then Break
  EndIf
Next i
:DSM15  ;At this point, Targetlist contains a list of all the files not
        ;present on the source
If DeleteTargetFiles != 1 Then Goto DSM20    ;Skip delete process if delete flag not set
;OK, Lets delete some files
If FileDelete(TargetList)==@TRUE Then Goto DSM20  ;Done it, so carry on
Message("Target Directory Delete Error","Error deleting files in %TargetDir%")
:DSM20  ;This bit copies the Source files to the Target if not the same
DirChange(SourceDir)
For j=1 To SourceNo
  Item=ItemExtract(j,SourceList,@TAB);Get each entry in the source list
  FC=FileCompare(Item,"%TargetDir%\%Item%")
  Switch FC
    Case 0                              ;Files are the same, so skip to next
      Break
    Case 1                              ;Source file is same size, but newer, so copy it
      FileCopy("%Item%","%TargetDir%\%Item%",@FALSE)
      Break
    Case 2                              ;Source file is newer, so copy it
      FileCopy("%Item%","%TargetDir%\%Item%",@FALSE)
      Break
    Case 3                              ;Target file missing, so copy it
      FileCopy("%Item%","%TargetDir%\%Item%",@FALSE)
      Break
    Case FC                             ;Target must be newer, so go on to next file
      If DowngradeTargetFiles==0 Then Break ;unless downgrade requested
      FileCopy("%Item%","%TargetDir%\%Item%",@FALSE) ;Downgrade requested, so copy anyway
  EndSwitch
:DSM22
Next j
Goto DSMEND

:DSM50  ;This bit copies the Source files to a newly created (empty) Target
DirChange(SourceDir)
BoxText(StrCat("Copying ",SourceDir))
If FileCopy(SourceList,TargetDir,@FALSE)==@TRUE Then Goto DSM55
Message("File Copy Error","Error Copying Source to Target")
:DSM55
Goto DSMEND

:DSMEND
DirChange(OrigDir)              ;Restore current Directory
Return

;****************************************************************************
; End of Directory Synchronization Module (DSM)
;****************************************************************************
;****************************************************************************
; End of Treecopy Utility (TU)
;****************************************************************************



Article ID:   W13806
Filename:   TreeCopy Utility - a Smarter XCOPY.txt
File Created: 2017:08:29:11:19:24
Last Updated: 2017:08:29:11:19:24