Skip to content

Using Photorec and a bash script to recover 51,407 images

A sad thing happened to my mother-in-law the other day. Somehow, one of her 1 TB hard drives that stores mountains of images (she is a professional photographer) got reformatted to a nice, fresh state, but certainly not what was wanted. She has a client that needs the images in just a couple of days, and so the race was on to see what I could do (remotely, using LogMeIn no less) to recover the data.

I turned to Photorec, and absolutely fantastic command line program that does a hard core scavenge of any disk, looking for known file headers, and tries to reconstruct a file based on its findings. I felt that, since the drive had simply been reformatted and not zeroed, with only one file being placed on the drive since the formatting, that the chances of finding the files was pretty good. Using another external hard drive as storage for recovered files, 15 hours later it had recovered 51,407 .JPGs, .NEFs, and .PSDs, woohoo!

Now one unfortunate byproduct of Photorec recovery is that, while much of the file’s metadata is still in place (modified/accessed timestamps, EXIF data, etc.), it didn’t recover filenames or folder structure. So I had over 51,000 images with random filenames in 130 different “recup” folders, mostly in chunks of the same creation date, but not entirely.

To solve this, I wrote a small little bash script to sort files into folders by modified date. I’m not super skilled at bash scripting, so it took me longer than it probably should of and is probably not very elegant, but it worked quite well in my case! I pointed the script at the recovered directories, ran it, and 3 minutes later it had created over 1300 folders based on the created/modified dates of the files, moved the files into the folders, and bam! I was pretty impressed with myself. 🙂

If anyone is looking for a similar script (couldn’t find one after an initial Google search last night) then feel free to take this one and modify to suit your needs. Obviously I can’t guarantee anything with it, but it shouldn’t eat your files if you set up the directories correctly. If you are nervous, change the “mv” command on line 27 to “cp” and you should be safer (although the script will of necessity run much slower). There are certainly some things that could be improved about the script (not hardcoding the 300 of ## number, not cd’ing into the source directory, etc.) but it worked in a pinch and didn’t need to be elegant. Hope it helps!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/bin/bash
# Sort files into folders based on their creation date.
#
 
# Indicate a path to the source folder of data to be sorted, and a destination folder where you want the sorted folders to be.
# Note: this will work better if the sorted directory is NOT inside the source directory, otherwise recursion might occur and the world might blow up.
SOURCE_DIR=~/Desktop/testsrc/
SORTED_DIR=~/Desktop/sorted/
sorted_count=0
 
# go into the first folder of the source folder
cd "$SOURCE_DIR";
 
# for each item in this folder
find . -type f -print | while read file; do 
 
	# Get the creation date of the item and store it in a variable
	file_date=`stat -f '%Sm' -t "%F" "$file"`;
 
	# Does a folder with this date already exist?
	if [ ! -d "$SORTED_DIR/$file_date" ]; then
		# If no, create the folder
		mkdir -p $SORTED_DIR/$file_date
	fi
 
	# Now move the file to the folder
	mv "$file" "$SORTED_DIR/$file_date/"
 
        # Provide some feedback to the user on our progress
	let "sorted_count += 1"
	if [[ "$sorted_count % 100" -eq "0" ]]; then
		echo "Sorted $sorted_count of 51,407" # Obviously the of count is hard coded 
	fi
 
done
 
echo "Finished."
Published inProgramming

4 Comments

  1. max max

    Exactly what I needed.
    For some unknown reason I had to change stat command call to:
    file_date=`stat -c %x "$file"|colrm 11`;
    In your version I had numerous errors because of unknown format string.
    Thank you.

  2. Will Will

    If you have space in your paths, you will get unexpected results.
    I highly recommend using “” around the path line 12 and TEST the script first….

    • Thanks Will, updated the script. Alternatively, you could also include a slash before any space when declaring your paths as well.

      And definitely, it should always go without saying that you should indeed be testing your stuff before you run.

  3. Ash Ash

    Recovering a hard drive for a friend, i wanted to sort the files by extension. The following worked for me :

    for x in `ls |grep recup` ; do for y in `ls $x` ; do declare ext=`echo $y |sed -e ‘s/\./\n/g’ |tail -n 1` ; if [ ! -d files.$ext ] ; then mkdir files.$ext ; fi ; mv $x/$y files.$ext ; done ; done

    mkdir files_no_ext
    for x in `ls |grep recup` ; do for y in `ls $x |grep -v ‘\.’` ; do mv $x/$y files_no_ext/ ; done ; done

    Joining Will’s recommecdation to test-run things first. Add echo before the commands that actually do anything, so they are displayed instead of executed

    But be carefull to either echo all of them, or none. I had a mishap with the 1st script, where mkdir was echo’d and mv was not. The result was that several files were overwritten under the name files.(extension) instead of being put into a directory with same name

Leave a Reply

Your email address will not be published. Required fields are marked *