Copy a filesystem

January 23, 2007

When you need to copy or move an entire filesystem, the first, most obvious, answers do not quite do the job. cp needs lots of flags to get the permissions, ownership, access times and so on to match. tar takes care of most of that, but it still doesn’t deal with special files (the most common being character or block devices, such as those you’d find in /dev). So there’s a little magic incantation I’ve memorised. It does the job, not 99% of the job, it just does the job.

If you have two volumes, let’s call them /data and /backup, and you want to copy everything from /data into /backup, then you’d do this:

# cd /data
# find . -print | cpio -pudvm /backup

And off it goes. Your inode attributes, special files, everything, just as it was in the /data filesystem. If there are other filesystems mounted under /data – eg., /data/customer1 and /data/customer2, then they’ll be backed up by this method. If that’s not what you want, then add -mount to the find command.

I used it recently when a hard disk was dying, and it contained the /home filesystem; just get a new disk, and off you go:

# mkfs.ext3 /dev/hdc1
# mount /dev/hdc1 /newhomes
# cd /home
# find . -print | cpio -pudvm /newhomes

And then just unmount the old one, edit the /etc/fstab to point to the new one, and remount it. A little bit of sed is easier to show than the editing… I’d use vi in real life:

# mount | grep home
/dev/hda1 on /home type ext3 (rw)
# umount /home
# grep home /etc/fstab
/dev/hda1    /home     ext3  defaults    0   2
# sed -i hda1 hdc1 /etc/fstab
# grep home /etc/fstab
/dev/hdc1    /home     ext3  defaults    0   2
# mount /home
# mount | grep home
/dev/hdc1 on /home type ext3 (rw)

The cpio switches are (with descriptions from a Solaris 9 man page):
-p (pass) Reads a list of file path names from the standard input and conditionally copies those files into the destination directory tree.
-d Creates directories as needed.
-m Retains previous file modification time. This option is ineffective on directories that are being copied.
-u Copies unconditionally. Normally, an older file will not replace a newer file with the same name.
-v Verbose. Prints a list of file and extended attribute names. When used with the -t option, the table of contents looks like the output of an ls -l command (see ls(1) ).

I don’t know why, but I find the order pudvm is stuck in my head, it just seems like a nice little word in its own right. And it’s been really helpful on a number of occasions.