#!/bin/sh
# exifdate2fs // wdoekes/2014 // Public Domain
# 
# Uses the EXIF dates in JPEG files and resets the filesystem mtime to
# the date contained in the EXIF info.
#
# Usage:
#
#     exifdate2fs fileA.jpg path/to/fileB.jpg ...
#     exifdate2fs -A
#
# After updating the mtime of the files, exifdate2fs continues to update
# the mtime of the paths that were touched as well. They are set to the
# same time as the newest file in that path.
#

dirdate() {
    stat -c%y "$1/`ls -t "$1" | head -n1`" |
        sed -re 's/(....)-(..)-(..) (..):(..):(..).*/\1\2\3\4\5.\6/'
}

jpegdate() {
    exiftran -d "$1" |
        sed -re '
            /0x(0132|9003|9004)/!d
            s/.*(....):(..):(..) (..):(..):(..)/\1\2\3\4\5.\6/
        ' | head -n1
}

setdate() {
    if test -z "$2"; then
        echo "$1: got empty date" >&2
        false
    else
        touch -t "$2" "$1"
        echo "$1: $2"
    fi
}

updatejpeg() {
    setdate "$1" "`jpegdate "$1"`"
}

updatedir() {
    setdate "$1/" "`dirdate "$1"`"
}

# Inlining dirname for 100x speed.
dirname() {
    fn="$1"
    if test "$fn" = ""; then
        echo .
    elif test "$fn" = "${fn%/*}"; then
        echo .
    else
        echo "${fn%/*}"
    fi
}

case "$*" in
'')
    echo 'See: exifdate2fs -h' >&2
    exit 1
    ;;
-h)
    echo 'exifdate2fs: Updates JPG/JPEG filesystem times with the EXIF '\
'time-it-was-taken'
    echo 'date.'
    echo 'Usage: exifdate2fs path/to/fileA.jpg path/to/fileB.jpg ...'
    echo 'Usage: exifdate2fs -A  # to do *.jpg/*.jpeg recursively from $PWD'
    ;;
-A)
    find . -type f '(' -iname '*.jpg' -or -iname '*.jpeg' ')' |
        xargs -d\\n "$0"
    ;;
*)
    # First update all the passed files.
    for file in "$@"; do
        updatejpeg "$file"
    done
    # Then check out which paths we've modified and alter those.
    for file in "$@"; do
        dirname "$file"
    done | sort -u | while read -r path; do
        updatedir "$path"
    done
    ;;
esac

# vim: set ts=8 sw=4 sts=4 et ai:
