#!/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: