Over the weekend, I wrote a small utility in ruby to backup my /Users directory to my external backup drive. Here it is: (script is downloadable here)
#!/usr/bin/ruby## Created by Tamara Temple on 2007-03-16.# Copyright (c) 2007. All rights reserved.require 'FileUtils'
include FileUtils::Verbose
LIBRARY_DIRS =
["./Library/Application Support",
"./Library/Keychains",",/Library/Mail","./Library/Mozilla","./Library/Preferences","./Library/Safari","./Library/StickiesDatabase","./Library/Workflows"]
def getBackDir(timestamp)
prefix = "/Volumes/BootBackup/Users"suffix = timestamp.strftime("%Y%m%d.%H%M%S")
backupdir = prefix + suffixprint "** backupdir: ", backupdir, "\n" if $DEBUG
backupdir
enddef getUserList(parentdir)
userlist = Dir.entries(parentdir)
if (!userlist.kind_of?(Array)) then raise "Internal Error: Dir.entries did not return an array." end
userlist.delete(".") # remove the working directory from the list (this will not affect the directory on the disk)
userlist.delete("..") # remove the parent directory from the list
userlist.delete(".localized") # remove an extraneous file from the /Users directory
print "** userlist: ", userlist.join(", "),"\n" if $DEBUG
userlist # return the userlistenddef getFileList()
files = Dir.entries('.')
if (!files.kind_of?(Array)) then raise "Internal Error: Dir.entries did not return an array." end
files.delete(".") # remove the reference to the directory itself. (note this will not remove the directory - files is an array not the directory)
files.delete("..") # remove the parent directory listing
files.delete(".Trash") # don't backup the trash
files.delete("Library") # remove the Library directory as we don't want it all in the backup
print "** files: ", files.join(", "),"\n" if $DEBUG
beginlibdirs = Dir.entries("./Library")
rescue Errno::ENOENT
libdirs = []
ensureif (!libdirs.kind_of?(Array)) then raise "Internal Error: Dir.entries did not return an array." end
end# Remove extraneous entrieslibdirs.delete(".")
libdirs.delete("..")
libdirs.delete(".localized")
libdirs.map! {|l| "./Library/" + l} # Need to add in the path to the Library subdirectories
print "** libdirs: ", libdirs.join(", "),"\n" if $DEBUG
libdirs = libdirs & LIBRARY_DIRS # get the intersection of library directories with the set we want to keep in backup
files = files + libdirsfiles.map! {|f| "'#{f}'"} # need to quote file names for find() command in backupUsers() procedure
print "** files: ", files.join(", "),"\n" if $DEBUG
files # return the file listenddef backupUsers(userlist,backupdir)
for user in userlist
mkdir("#{backupdir}/#{user}") unless $DEBUG
print "** mkdir #{backupdir}/#{user}","\n" if $DEBUG
cd(user) do # change directories in a block, at the end of the block, direcotry will go back to previous working directory
files = getFileList()
begin`find #{files.join(" ")} -print | cpio -pdv #{backupdir}/#{user}` unless $DEBUG
print "** find:", files.join(", ")," | cpio: ", "#{backupdir}/#{user}","\n" if $DEBUG
rescuewarn "Error with backing up #{user}: #{$!}\nContinuing with next user."endendendendbackupdir = getBackDir(Time.now)
mkdir(backupdir)
cd("/Users") do # change directories in a block, at the end of the block, directory will go back to the previous working directory
userlist = getUserList("/Users")
backupUsers(userlist,backupdir)
end