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

10,770

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.

Solution 4

I believe what you want can also be achieved with ditto yesterdays_backup todays_backup. By default, ditto does a recursive copy that preserves hard links, ACLs, and extended attributes.

Share:
10,770

Related videos on Youtube

Admin
Author by

Admin

Updated on September 17, 2022

Comments

  • Admin
    Admin over 1 year

    I'm trying to copy a directory tree recursively preserving hardlinks to the file. Using gnu cp, this would work with the -l flag. cp would then recreate the directory structure, but wouldn't need to copy the contents of each file.

    This is preliminary to a backup, first I want to make a cheap (hardlinked) copy of the previous backup and then rsync the source directory over this copy. Roughly:

     cp -r -l yesterdays_backup todays_backup
     rsync -a source_dir todays_backup
    

    Unfortunately, OSX's cp doesn't support the -l flag, as far as I can tell, cpio doesn't support recursive copying. The other alternative is pax, but that leads to the entire directory structure being copied:

     pax -rw backups/yesterdays_backup backups/todays_backup
    

    transforms:

     yesterdays_backup
     |
      \source_dir (...)
    

    to:

     todays_backup
     |
      \backups
              \yesterdays_backup
                                \source_dir(...)
    

    There should be an easy/obvious way to do this, but I'm currently stumped... Any alternatives to cpio and pax? I'd like to avoid having to install gnu cp.

    I'm aware of Timemachine, but that won't properly back up encrypted directories incrementally.

  • Florenz Kley
    Florenz Kley about 13 years
    the problem is that the copy is not cheap any more when the objective is to create hard links across directory scope. ditto can preserve them when they exist, but it can't be told to link instead of creating a duplicate.
  • Chris F Carroll
    Chris F Carroll over 6 years
    I don't think ditto can even be told to preserve directory hard links. man page says it only does file hard links
  • lpacheco
    lpacheco about 4 years
    What if source and destination are in different disks? Would rsync still preserve hard links from source in the copy made in the destination?
  • MrT
    MrT about 4 years
    Yes, obviously they won't be hard links to the original disk, however they will be hard links within the copy.
  • Scott - Слава Україні
    Scott - Слава Україні over 3 years
    Do you mean -L or -l?  They’re not the same thing.  The question is primarily about the -l; I wonder whether you missed the point.