Fun with bash and old photo libraries.

It recently dawned on me I had huge swathes of my photo collection entirely gone. Something like 3 years that were nowhere to be found on flickr or my main PC or Mac. I’m not sure how this gap appeared but I eventually found the files in a backup of my Mac from quite some time ago (I keep everything until I really need the space). Problem was it was in an old Aperture directory structure and I really just wanted to get the pictures out and sort through them from scratch. I’d used different cameras, some of the pictures weren’t mine etc. etc.

So to sort through it all I wrote a small bash script. First argument in quotes is the backup/source and the second argument in quotes is the destination. It uses imagemagicks identify command and will copy the files to:

destination/camera model/date taken/name.count.jpg

count will iterate up if the file exists, if something goes wrong it will not copy the file but will print an F instead of a dot and write a log to extractPhotos.err.


#!/bin/bash
SOURCE="$1"
DEST="$2"
cd "$SOURCE"

function getSafeFilename {
    local SAFE="$1"
    local COUNT=1
    while [ -e "$SAFE" ] 
    do
        local DIR=$(dirname "$1")
        local BASE=$(basename "$1")
        local NAME=${BASE%.*}
        SAFE="$DIR/$NAME.$COUNT.JPG"
        ((COUNT++))
    done

    echo $SAFE
}

# Identify all JPG images that are not thumbnails.
find . -iname *.jpg | grep -iv thumb | while read -r jpeg 
do
    # Identify Model of Camera
    MODEL=$(identify -format "%[EXIF:Model]" "$jpeg" | sed 's/ *$//g')
    # Identify Date taken YYYY-MM-DD
    DATETAKEN=$(identify -format "%[EXIF:DateTime]" "$jpeg")
    DATEDAY=$(echo "$DATETAKEN" | cut -d' ' -f1)
    # Get base photo name
    PHOTO=$(basename "$jpeg")

    # Set camera model if undefined
    len=${#MODEL}
    if [[ "$len" -lt "1" ]]; then
        MODEL="Unknown"
    fi

    # Make destination directory
    DESTDIR="$DEST/$MODEL/$DATEDAY"
    if [ ! -d "$DESTDIR" ]; then
        mkdir -p "$DESTDIR"
    fi

    # Check for existing picture in that directory, if so, modify destination name, iterate if nec. (move to function)
    SAFEFILE=$(getSafeFilename "$DEST/$MODEL/$DATEDAY/$PHOTO")

    # Copy file!
    cp -n "$jpeg" "$SAFEFILE" && echo -n "." || (echo -n "F"; echo "Failed: $jpeg to $SAFEFILE" >> extractPhotos.err)

    # End
    unset MODEL
    unset DATETAKEN
    unset DATEDAY
    unset DESTDIR
    unset SAFEFILE
    unset len
# End
done
This entry was posted in Computer, Photography, Programming and tagged , , , , , . Bookmark the permalink.