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.

How to Subtract one Directory Tree from Another

Keywords:     directory difference

Here's a handy utility for subtracting one directory tree from another. Useful for situations where you have a number of similar PC images and want to keep one "basic" image and a number of "overlays" (Directory Differencing Module)

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

DDM - Directory differencing module: "Subtracts" the contents of a source directory tree from a target directory tree. The source directory tree is unmodified. The target directory tree is modified by removing all files that are identical to the source directory files, in revision and location, leaving only those files that are different. Ideal for developing upgrade overlays for PC configurations, where you want to know what files have been upgraded so that you can copy those files to other workstations.



;*****************************************************************************
; DIRECTORY DIFFERENCING MODULE  (DDM)
; Written by E.Tippelt  100115.3301@compuserve.com
; Will differentiate the Source and Target directories
; IDENTICAL files present in the source and target will be deleted in the target
; even if date and time stamps are different
; Target will be left with only files that were additional or updated to source
;*****************************************************************************
:CDTS1
SourceRoot=askline("GET SOURCE DIRECTORY","Please specify source directory","")
if !DirExist(SourceRoot)
  Message("ENTRY ERROR","Source Directory does not exist, Please re-enter")
  goto CDTS1
endif
:CDTS2  
TargetRoot=askline("GET TARGET DIRECTORY","Please specify target directory","")
if !DirExist(TargetRoot)
  Message("ENTRY ERROR","Target Directory does not exist, Please re-enter")
  goto CDTS2
endif
TargetDrive=StrCat(StrSub(TargetRoot,1,2),"\")     ;Get the target drive letter
Boxopen("Directory Compare Status","Getting Subdirectory list")
level=0
treelist=""
treelist%level%=SourceRoot
:CDTS5
if treelist%level%==""
  boxtext("Subdirectory list complete")
  delay(1)
  goto CDTS10        ;Got the directory list, now do something with it!
else
  gosub CDTS50
endif
goto CDTS5

:CDTS10
;The variable TREELIST now contains a space delimited, fully pathed, list of 
;all the 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," ")
 ;message("Number of Directories",dr)

;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 = dr to 2 by -1  ;k=1 represents the root directories, so leave it out
 SourceDir=itemextract(k,treelist," ")
 TargetDir=StrReplace(SourceDir,SourceRoot,TargetRoot)
 gosub ddm1     ;do the comparison
next k
;Now do the "root" directories, but dump the trailing \ 
SourceDir=StrSub(SourceRoot,1,StrLen(SourceRoot)-1)
TargetDir=StrSub(TargetRoot,1,StrLen(TargetRoot)-1)

gosub ddm1      ;Do the root directories

boxshut()
Message("Directory Compare Status","Directory Compare Complete")
Exit 
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;SUBROUTINES
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

;*****************************************************************************
;GET DIRECTORIES AT A GIVEN LEVEL IN THE TREE
;*****************************************************************************
 
:CDTS50     
treelist=StrCat(treelist," ",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," ")  ;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," ")
 gosub CDTS60
 if PathedDirList!="" then treelist%level%=strcat(treelist%level%," ",PathedDirList)
next i
 treelist%level%=strtrim(treelist%level%)
return

;*****************************************************************************
;GET SUBDIRECTORIES AT A GIVEN LEVEL IN THE TREE
;*****************************************************************************
:CDTS60     
;Entry parameters:
;SrcDir
;level
  slash=""
  length=strlen(SrcDir)
  Last=strsub(SrcDir,length,1)
  if last!="\" then slash="\"
DirChange(SrcDir)
DirList=DirItemize("*.*")
DirNo=ItemCount(Dirlist," ")      ;Count the entries in DirList
PathedDirList=""
if DirNo==0 then return
for j=1 to DirNo
  Dir=ItemExtract(j,DirList," ")  ;Get each entry in the directory list
  Dir=StrCat(SrcDir,slash,Dir)
 PathedDirList=strcat(PathedDirList," ",Dir)
next j
PathedDirList=strtrim(PathedDirList) ;Fully pathed list of subdirectories
return                               ;at a given level in the tree
                                     ;Becomes the treelist%level% for the next level
                                     
;****************************************************************************
; Directory Difference Subroutine
;****************************************************************************
:DDM1
;Entry parameters:
;SourceDir="C:\toolkit"
;TargetDir="C:\test"
boxtext("Comparing %sourcedir%%@crlf%and %targetdir%")
Filetype="*.*"
:DDM5                           ;Start Here
OrigDir=DirGet()                ;Save current Directory
if !DirExist("%SourceDir%")
  Message("Compare Error", "Source Directory does not exist")
  goto DDMEND
endif
if !DirExist("%TargetDir%") then goto bye   ;Nothing to do

:DDM10
if Filetype=="" then Filetype="*.*"
SourceList=Fileitemize("%SourceDir%\%Filetype%")
TargetList=Fileitemize("%TargetDir%\%Filetype%")
SourceNo=ItemCount(Sourcelist," ")      ;Count the entries in SourceList
TargetNo=ItemCount(TargetList," ")      ;Count the entries in TargetList
if TargetNo==0 then goto DDMEND ;Nothing to remove from target!

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," ")        ;Get each entry in the source list
  Pos=ItemLocate(Item,TargetList," ")       ;See if present in target list
  if pos !=0
    TargetList=ItemRemove(pos,TargetList," ") ;if present, delete the item
    TargetNo=TargetNo-1
    if TargetNo==0 then break
  endif
next i
:DDM20  ;This bit deletes Source files in the Target Directory if exactly the same
DirChange(SourceDir)
for j=1 to SourceNo
  Item=ItemExtract(j,SourceList," ");Get each entry in the source list
  FC=FileCompare(Item,"%TargetDir%\%Item%")
  Switch FC
    Case 0                              ;Files are the same, so delete in target
      if FileDelete("%TargetDir%\%Item%")==@True ;Done it, so carry on
        break
      else
        Message("Delete failed in Target Directory","File = %TargetDir%\%Item%")
      endif
      break
    Case FC                             ;Files are different, so do nothing
      break                             
  EndSwitch
:DDM22
next j                                       
goto DDMEND


:DDMEND   ;Check to see if directory is empty and can be deleted
if Diritemize("%TargetDir%\*.*")!="" then goto bye  ;found a subdirectory
DirChange(TargetDrive)  ;Change to root of target drive for possible DirRemove
if Fileitemize("%TargetDir%\*.*")=="" 
  if TargetDrive!="%TargetDir%\" then DirRemove("%TargetDir%")
endif
:bye
DirChange(OrigDir)              ;Restore current Directory
return

;****************************************************************************
; End of Directory Difference Module (DDM)
;****************************************************************************
                                     



Article ID:   W13800
Filename:   Subtract one Directory Tree from Another.txt
File Created: 2017:08:29:11:17:52
Last Updated: 2017:08:29:11:17:52