MacOS X: /usr/bin/ditto and backup

dankogai@dan.co.jp

Overview

Josh Wood responded to MacOS X: Backup and Restore Entire Volume, saying there is a command called /usr/bin/ditto that behaves like CpMac, but better in terms that it preserves ownerships, permissions, and other file/folder attributes. I've been a user of both Unix and Mac for more than 12 years but this is the first time I got to know this command. As a matter of fact I searched /usr/bin/ditto via google and found only 3 instances, 2 of which unrelated to MacOS X.

However, "man ditto" did work! This fact alone is better than CpMac which requires developer tool. I took a look at it and thought it would be THE solution. In consequence, not quite.

The biggest problem is its awkward treatment of source directories.

ditto -rsrcFork dir1 dir2 ... dstdir

Is NOT analogous to

CpMac dir1 dir2 ... dstdir

But rather

CpMac dir1/* dir2/* ... dstdir

See the difference? Instead of creating dir1, dir2... under dstdir and copy its contents, ditto splats its contents to dstdir.

Still the quick tests showed that ditto does copy resource forks and file attributes. So I came up with the script below.

The Script

This is the script I spend 30 seconds to write. It's just 30 seconds worth so it comes with no comment but a decent perl programmer should get the idea pretty quick

#!/usr/bin/perl

my $DstDir = shift;
-d $DstDir or help();
$DstDir =~ m,^/Volumes/,o or help("$DstDir is not volume!");

my @Exclude = (
               '.vol',
               'dev',
               'Volumes',
               );

my %Exclude = map {$_ => 1} @Exclude;
my @Items = ();

opendir D, '/' or die "$!";
for my $i (grep !/^\.\.?$/o, readdir(D)){
    $Exclude{$i} and next;
    push @Items, $i;
}
closedir D;

for my $i (@Items){
    if (-l "/$i"){
        my $l = readlink "/$i";
        print "/$i -> $l\n";
        symlink $l, "$DstDir/$i" or die "$!";
    }else{
        system 'ditto', '-V', '-rsrcFork', "/$i", "$DstDir/$i";
    }
}

#
mkdir "$DstDir/.vol", 0444 or die "$!";
mkdir "$DstDir/dev", 0555 or die "$!";
mkdir "$DstDir/Volumes", 1777 or die "$!";

sub help(){
    $_[0] and print "Error: $_[0]\n";
    print <<"";
Usage:   $0 dstdir

        exit(0);
}

The idea is simple. Dump everything on root directory except for .vol, dev and Volumes and create these directories later with proper permissions.

I su'd and ran the script. I used PowerBook G3/400 (Firewire; AKA pismo) with expansion bay HDD attached. I used expbay drive as a target drive. It did what I expected...well, almost. Here is the outcome.

Conclusion

It still seems that the simplest and safest way to backup the volume is the method I mentioned in MacOS X: Backup and Restore Entire Volume. ditto-based solution is better indeed in terms that it requires no MacOS 9.x. However, It is still not as easy as dragging the volume icon to another.

History of this Document

2001.07.01
1st appearance