Best way to copy all files, ignoring errors?

I have a partially corrupted HD that can not be repaired by Disk Utility, but which can be mounted read-only making the data on it accessible.

I am trying to copy all the recoverable contents onto a spare HD, but every method I try fails when an error is encountered - leaving the remaining files un-copied.

  • Finder - Fails
  • SuperDuper - Fails
  • Ditto (terminal command) - Fails

I was hoping that Ditto would do the trick, the Ditto man page says:

ditto returns 0 if everything is copied, otherwise non-zero. ditto almost never gives up, preferring to report errors along the way. Diagnostic messages will be printed to standard error.

I have submitted a bug to Apple re ditto failing to perform as advertised.

Any other ideas?


I use cp -Rfpv sourcefile destinationfile with success on a pretty regular basis.

  • cp = copy

  • R = maintains file hierarchies, also in -R mode, cp will continue copying even if errors are detected.)

  • f = if an existing destination file cannot be opened, remove it and try again

  • p = preserve file modification timestamps

  • v = verbose mode, displays files transferred as it progresses

  • sourcefile = data you want to copy

  • destinationfile = directory/drive you want to copy to


If a file cannot be copied due to an error, the job will proceed and you should see logging like:

cp: sourcefile/someBadFile.txt: Input/output error


Try Gnu ddrescue -- it's a data recovery program that does block-based copying with corrupt data recovery during the copy operations. You can get it for OS X if you're using Homebrew by typing in an Terminal window:

brew install ddrescue

A guide on arstechnica describes how to rescue a failed disk using ddrescue. Make sure you read through the guide, as it contains helpful information. Here is a gist on how to get there.

  • Locate the drive using diskutil list. The identifier column is what you are looking for:

    /dev/disk1
       #:                       TYPE NAME                    SIZE       IDENTIFIER
       0:      GUID_partition_scheme                        *750.2 GB   disk1
       1:                        EFI EFI                     209.7 MB   disk1s1
       2:                  Apple_HFS Macintosh HD 2          80.0 GB    disk1s2
       3:                  Apple_HFS Home                    509.1 GB   disk1s3
    
  • Unmount the disk in question:

    diskutil unmount /dev/disk1s3    
    
  • Start a rescue operation of the disk into an image. Make sure the location of Rescue.dmg is replaced with your desired location.

    sudo /usr/local/bin/ddrescue -v -n -c 4096 /dev/disk1s3 Rescue.dmg Rescue.log
    
  • Recover the image onto a new drive:

    sudo /usr/local/bin/ddrescue --force -v -c 4096 Rescue.dmg /dev/disk2s0 recovery.log
    

Be advised to also read the manual of ddrescue to educate yourself on the available options by running man ddrescue.


I like using rsync in order to copy files from a corrupted source to a functional destination:

rsync -auv --delete --ignore-errors /path/to/source/ /path/to/destination/

Where:

-a = "archive mode" = recurses into directories, copies symlinks as symlinks, preserves permissions, times, groups and special files, also preserves owner (when owner = root) and devices (when owner = root)

-u = skips the file in source if its corresponding copy in destination is newer

-v = verbose output

--delete = files in destination that do not exist on source will be deleted

--ignore-errors = deletes a file/directory in case of I/O error during the copy process


This Macworld hint suggests using dd to make a bit-by-bit copy (ignoring errors) then mounting the resultant image in Finder to recover your files. I've not tried it, but it sounds like it might work.


You might consider using the dd command to perform a block-by-block copy from your corrupt HDD to your new HDD.

Assuming your new-HDD (/dev/disk2) is of equal or greater size than your corrupt-HDD (/dev/disk1), then you can issue:

dd if=/dev/disk1 of=/dev/disk2 bs=4096 conv=notrunc,noerror

blocksized @ 4k, don't truncate any data blocks, ignore all errors

To find the device names, run mount from Terminal first.