DaveHope.co.uk

Sorting your photos with Bash

In early 2009 my Buffalo Terrastation died. I replaced a faulty RAID-5 member and when rebuilding the array something went horribly wrong and I lost a lot of data. Inspired by a colleague who’d written a PowerShell script to sort some photos, I decided to write a bash script to sort all the photos stored on my Linux HTPC that I’d not got around to sorting since my data loss.

The below script will find all the JPG images in a directory and move them into a YYYY/MM/DD directory structure, preserving the original file name.

#!/bin/bash
cfgSource="/media/media/Pictures/ToSort/"
cfgDestRoot="/media/media/Pictures/Sorted/"

for f in $(find $cfgSource -iname "*.jpg" -o -iname "*.nef")
do
        # Make sure the file we've been given by find actually exists.
        if [ -f $f ]; then
                timestamp="$(identify -format '%[exif:DateTimeOriginal]' $f)"
                timestamp=${timestamp%T*}


                # Looks like there are two possible timestamp formats in my
                # photos:
                #       2008-05-05T14:46:47.16+01:00
                #       2009:02:28 12:57:50
                # Thankfully, cut will handle both these formats.
                y=$(echo $timestamp | cut -c 1-4)
                m=$(echo $timestamp | cut -c 6-7)
                d=$(echo $timestamp | cut -c 9-10)

                destFile=$cfgDestRoot$y/$m/$d/$(basename $f)

                # If the directory doesn't exist recursively create it.
                if [ ! -d $cfgDestRoot$y/$m/$d ]; then
                        mkdir "$cfgDestRoot$y/$m/$d" -p
                fi
				
                # Move the file.
                if [ -f $destFile ]; then
                        # Existing file found.

                        # Is it the same file? If so, delete the file we're processing.
                        md5src=$(md5sum $f)
                        md5src=${md5src% *}
                        md5dst=$(md5sum $destFile)
                        md5dst=${md5dst% *}
                        if [ $md5src = $md5dst ]; then
                                echo "Duplicate found, discarding identical file"
                                rm $f
                        else
                                # Is this file larger than the existing one?
                                sizeSrc=$(stat -c%s $f)
                                sizeDst=$(stat -c%s $destFile)
                                if [ $sizeSrc -gt $sizeDst ]; then
                                        echo "Duplicate Found, keeping the larger file."
                                        mv $f $destFile
                                else
                                        rm $f
                                fi
                        fi
                else
                        mv $f $destFile
                        echo "Moved $f to $destFile"
                fi
        fi
done

It’s quick to process JPG files, but will take substantially longer to process RAW files. Much quicker than sorting them by hand, enjoy.

Comments are closed.