cp -r -l in MacOS (recursive copy preserving hard links)

Solution 1:

It is easy enough to install cp from MacPorts, however, if you don't want to, or want to create a portable script, then you have three options:

rsync

rsync --archive --link-dest=../yesterdays_backup backups/yesterdays_backup\
   backups/todays_backup

cpio

mkdir backups/todays_backup
cd backups/yesterdays_backup
find . -print | cpio -p -al ../todays_backup

pax

mkdir backups/todays_backup
cd backups/yesterdays_backup
pax -rwl . ../todays_backup

Solution 2:

It's easy to install the coreutils package from MacPorts which contains the GNU cp command renamed to gcp.

But even better, newer versions of rsync, including the one in OS X 10.5 at least, support the --link-dest option which should eliminate the need for the initial cp -al. See here. It's good practice to use the -E option, too, to copy extended attributes, ACLs, etc.

Solution 3:

The macOS Finder copy does it right, preserving hard links, even to a different Volume. But only if it is a simple 1-item copy without joining.

  • You see if it works right away, because if it does, the amount "to be copied" is the net size like it is reported by du. If the copy is for some reason not hardlink-preserving, you see a size too big and can stop immediately.
  • If you need to copy or join parts of a more complicated folder structure, move the source into a parent folder used for the copy. Moving the copied items later on the destination to the right places obviously preserves the hard links.