This is a simple this is a script for data recovery from damaged disks that I (Andy Gaskell) did. It is assumed that it will take several attempts to copy some of the files from the disk (HDD, DVD or CDR). It should be fine for windows or linux. You just need to set the user variables at the top of the script.
Notes from real-world use:
The whole code is just pasted in below, it's got a fair few comments in, but any bits that don't make sense, just add a question.
# this is a script for data recovery from damaged disks
# it is assumed that it will take several attempts to copy
# some of the files from the disk (HDD, DVD or CDR).
# it should be fine for windows or linux.
# you just need to set the user variables at the top of the script.
# Andy G. April 08.
puts "cdr_recovery.tcl script"
# user vars
# the folder to try to copy files from
set sourcedir "/media/cdrom"
# the folder to try to copy them to
set targetdir "/home/andy/980720_1616_linux_s1"
# the number of time to re-try
set numits 100
# util vars
set count 0
set totalsize 0
# create the list of files from a big glob
set sourcefilelist [ glob -nocomplain -directory $sourcedir \
* \
*/* \
*/*/* \
*/*/*/* \
*/*/*/*/* \
*/*/*/*/*/* \
*/*/*/*/*/*/* \
*/*/*/*/*/*/*/* \
]
if { [ llength $sourcefilelist ] == 0 } {
puts "no matches"
exit
}
# loop through the file list building up an array with all the info in
foreach sourcefile $sourcefilelist {
incr count
# build up the data array
set filearray(sfile,$count) "$sourcefile"
set filearray(size,$count) "[file size $sourcefile]"
set filearray(date,$count) "[clock format [file atime $sourcefile] -format "%H:%M:%S %D"]"
set filearray(trimfile,$count) "[string trimleft $sourcefile "$sourcedir"]"
set filearray(fileonly,$count) "[file tail $sourcefile]"
set filearray(folderonly,$count) "[string trimleft [file dirname $filearray(sfile,$count)] "$sourcedir" ]"
set filearray(done,$count) 0
# print out some general info
puts "$filearray(sfile,$count)"
puts " number - $count"
puts " size - $filearray(size,$count) bytes"
puts " date - $filearray(date,$count)"
puts " trim - $filearray(trimfile,$count)"
puts " file - $filearray(fileonly,$count)"
puts " dir - $filearray(folderonly,$count)"
# keep a running total of all the file's sizes
set totalsize [ expr $totalsize + $filearray(size,$count) ]
}
# save the number of files
set numfiles $count
# print some useful sumary info
puts " "
puts "total size: $totalsize bytes"
puts "file count: $numfiles"
puts " "
# do them all numits num of times
for { set it 1 } { $it <= $numits } { incr it } {
# loop through the array
for { set count 1 } { $count <= $numfiles } { incr count } {
# if the file is not done already
if { $filearray(done,$count) == 0 } {
puts "$filearray(sfile,$count)"
puts " number - $count"
puts " size - $filearray(size,$count) bytes"
puts " date - $filearray(date,$count)"
puts " trim - $filearray(trimfile,$count)"
puts " file - $filearray(fileonly,$count)"
puts " dir - $filearray(folderonly,$count)"
# see if the target dir exists
if { [ file isdirectory $targetdir/$filearray(folderonly,$count) ] == 1 } {
puts " exists: $targetdir/$filearray(folderonly,$count) "
} else {
puts " doesnt exist: $targetdir/$filearray(folderonly,$count) "
file mkdir "$targetdir/$filearray(folderonly,$count)"
puts " created it"
}
puts " about to copy:"
puts " $filearray(sfile,$count) "
puts " to"
puts " $targetdir/$filearray(folderonly,$count)"
if { [ file exists $targetdir/$filearray(trimfile,$count) ] == 1 } {
# the file already exists
puts " file already exixts, no need to copy"
set filearray(done,$count) 1
} elseif { [ catch { file copy -force $filearray(sfile,$count) $targetdir/$filearray(folderonly,$count) } errorvar ] } {
# catch an error if there is one, and print details
puts " error: $errorvar"
} else {
# if there is no error, say so, and set done to true
puts " no error, copied ok"
set filearray(done,$count) 1
}
puts " "
}
}
puts "it $it"
puts " "
}
puts "script complete"AMG: See Directory recursion for several possible replacements for [set sourcefilelist [glob ...]]].
HJG Maybe a program like ddrescue [L1 ] or dd_rescue [L2 ] already does all you need.