#!/bin/sh # cpr_sbio: CoPy Recursively but Skip Bad IO # # Copies from a directory to a directory, but skips if not readable # and deletes from destination if any problems. # # Use case: trying to get data off a RAID array with problems, or # copying files out of a filesystem with problems. # # Bryan Smith - bryanesmith at gmail.com # Method for fatal errors fatal_e () { block_p $1 exit $2 } # Method to print out failed files file_failed () { echo "File Failed: $1" } # Method to print a block for easy reading block_p () { echo; echo $1; echo } if [ "$#" -ne "2" ]; then fatal_e "Two parameters required: /path/to/input /path/to/output" 1 fi In=$1 Out=$2 if [ ! -e $In ]; then fatal_e "Specified input directory ($In) doesn't exist." 2 fi if [ ! -e $Out ]; then mkdir $Out fi if [ ! -e $Out ]; then fatal_e "Specified input directory ($Out) doesn't exist." 2 fi Files=`find $In` Success=0 Failed=0 for File in $Files do OutPath="${Out}/${File}" SuccessFlag="0" # Only attempt copy if file is readable if [ -r $File ]; then if [ -f $File ]; then cp $File $OutPath # If copy had problem, assume I/O error if [ "$?" -ne "0" ]; then rm $OutPath else Success=`expr $Success + 1` SuccessFlag="1" fi elif [ -d $File ]; then if [ ! -e $OutPath ]; then mkdir $OutPath SuccessFlag="1" fi fi fi # If file readable if [ "$SuccessFlag" -ne "1" ]; then # Any non-regular and non-directory file is assumed failed. # This will exclude symbolic links and (hopefully) bad files. file_failed $File Failed=`expr $Failed + 1` fi done block_p "Fin. $Success successful copies, $Failed failed copies."