Version 0 of Directory Tree Synchronization

Updated 2004-08-31 18:33:52 by GPS

George Peter Staplin: I keep some backups on a 2nd hard disk, as a sort of poor-man's RAID. I use the following tool to synchronize two directory trees.


 #!/usr/bin/env tclsh8.4
 #By George Peter Staplin

 proc build.tree.stat.info {ar_ptr dir} {
  upvar $ar_ptr ar
  array set ar {}
  foreach f [glob -nocomplain [file join $dir *]] {
   if {[file isdirectory $f]} {
    build.tree.stat.info ar $f
   } else {
    set ar($f) [file size $f]
   }
  }
 }

 proc copy.from.to {from to} {
  puts "COPYING $from $to"
  file mkdir [file dirname $to]
  file copy -force $from $to
 }

 proc sync.trees {a_ptr b_ptr} {
  upvar $a_ptr a
  upvar $b_ptr b

  #From a to b
  foreach {f size} [array get a] {
   if {![info exists b($f)]} {
    copy.from.to [file join $::tree_a_directory $f] [file join $::tree_b_directory $f]
   } else { 
    if {$size != [set b($f)]} {
     puts stderr "size for $f in $::tree_a_directory doesn't match $::tree_b_directory"
    } 
   } 
  }
  #From b to a
  foreach f [lsort -unique [concat [array names a] [array names b]]] {
   if {![info exists a($f)]} {
    copy.from.to [file join $::tree_b_directory $f] [file join $::tree_a_directory $f]
   }
  }
 }
 proc main {argc argv} {
  if {2 != $argc} {
   puts stderr "syntax: tree-a tree-b"
   exit 1
  }

  set oldwd [pwd]
  cd [set ::tree_a_directory [file normalize [lindex $argv 0]]]
  build.tree.stat.info a {}
  #parray a
  cd $oldwd
  cd [set ::tree_b_directory [file normalize [lindex $argv 1]]]
  build.tree.stat.info b {}
  #parray b

  sync.trees a b
 }
 main $::argc $::argv

[Category ?]