Nino’s Reminders

June 19, 2006

Recover accidentally deleted files

Filed under: FreeBSD — nino @ 16:28

The above is not impossible, but it is very difficult. First of all, the following procedure works only for textual files, but it can still be useful – for example, to recover sources you were programming for the last three months and accidentally deleted. So, how do you go from here?

First, stop writing anything to the partition where deleted files were located!

Second, make a disk dump:
dd if=/dev/[disk and partition label] of=deleted-file bs=1m

Disk and partition label can be found by issuing df. For example, my /usr partition was mounted on /dev/ad0s1d. Don’t forget that output file (of parameter) should reside on another partition. The output file will be equal in size to the size of the partition being dumped. If you don’t have enough space on another partitions of the same disk, insert another disk or mount some resource over the network.

Now you have a raw data file. You can relax a bit now – your data, provided it was still undamaged at the moment you made the image, is safe now, meaning it can’t get overwritten anymore.

Next step is to try and extract the data you need. For that, you need one important thing – a unique string. You have to remember at least some specific word or phrase you used in the lost file(s) in order to recover them in a feasible amount of time. When you have that unique string, you can do the following:

grep -a -B50 -A50 "unique-string" deleted-file

What you are doing now is grep’ing your partition for the deleted file. -a tells grep to treat the input file as text even though it’s binary. -B and -A tell grep to display (in this case) 50 lines of context before and after the found unique string.

That’s the principle, but you won’t do it that way in reality. So, the complete solution:

for (( i = 0 ; i < [nnn] ; i++ ))
do
echo $i > progress && dd if=deleted-file bs=1m skip=${i}00 count=100 2> /dev/null | grep -a -B50 -A50 "unique-string" >> results.output
done

[nnn] should be the size of partition dump file in megabytes divided by 100.

The above loops for [nnn] times, echoes current iteration in a filename called progress, takes a 100MB chunk of data (block size of 1m times count of blocks), skips blocks already read, redirects standard error to null, grep’s the incoming data for unique string and outputs all matches to the results file. Grep has to be fed the data in small chunks (certainly less than 1GB) instead of entire partition image because it otherwise exits with a cryptic “out of memory” error.

Blog at WordPress.com.