^ home

Time Machine

This is a simple script that copies all the files that have changed since the last backup from a source folder to a destination folder.

require 'fileutils'
include FileUtils::Verbose

$ignore = []
$group = []

def backup(dir)
    files = Dir[ File.join(dir, '*') ]
    files.each { |f|
        if ignore?(f)
        elsif group?(f) or !File.directory?(f)
          copy(f) if modified?(f)
        else
          backup(f)
        end
      }
end

def modified?(f)
  if File.directory?(f)
    Dir[ File.join(f, '*') ].each {|o| return true if modified?(o)}
    return false
  else
    return File.lstat(f).mtime > $last_backup
  end
end

def copy(f)
  dest = File.join($copy_destination, source_relative(f))
  cmd = "ditto '#{f}' '#{dest}'"
  system(cmd)
  puts(source_relative(f))
end

def source_relative(path)
  p = path.dup
  p[$source + "/"] = ""
  return p
end

def ignore(path) $ignore << path end
def group(path) $group << path end

def ignore?(path)
  path = source_relative(path)
  $ignore.each {|p| return true if path[p]}
  return false
end

def group?(path)
    path = source_relative(path)
    $group.each {|p| return true if path[p]}
    return false
end

def check_destination()
  raise "Destination not found: #{$destination}" unless File.exist?($destination)
  dates = Dir[ File.join($destination, '20??-??-??')]
  if dates.size == 0 then
    $last_backup = Time.local(Time.now.year, Time.now.month, Time.now.day)
  else
    start = dates[-1]
    start.scan(/(....)-(..)-(..)/) {|y,m,d| $last_backup = Time.local(y,m,d)}
  end
  $copy_destination = File.join($destination, sprintf("%04i-%02i-%02i", Time.now.year, Time.now.month, Time.now.day))
  puts "Backing up from #{$last_backup} to #{$copy_destination}"
  puts
end

$options = ARGV[0] || "time-machine.config"
raise "Options file '#{$options}' not found" unless File.exist?($options)
File.open($options) {|f| eval(f.read)}

raise "No source directory" unless $source
raise "No destination directory" unless $destination

check_destination()
backup($source)

A sample configuration file:

$source = "/Users/niklas/Documents"
$destination = "/Users/niklas/Documents/_Backup"

ignore(/^_Arkiv/)
ignore(/^_Backup/)
ignore(/\/_darcs/)
ignore(/\/Subversion/)

group(/\..*$/)

 

home ^


© 2012, Niklas Frykholm, [email protected]