Skip to content

Instantly share code, notes, and snippets.

@ncherro
Forked from jvhaarst/movedigiphotos.bash
Created December 6, 2017 03:11
Show Gist options
  • Save ncherro/0050eb4c6e10b548238071792b0a1c1a to your computer and use it in GitHub Desktop.
Save ncherro/0050eb4c6e10b548238071792b0a1c1a to your computer and use it in GitHub Desktop.
Bash script to move images, based on exif data and file timestamp
#!/bin/bash
# Reads EXIF creation date from all .JPG files in the
# current directory and moves them carefully under
#
# $BASEDIR/YYYY/YYYY-MM/YYYY-MM-DD/
#
# ...where 'carefully' means that it does not overwrite
# differing files if they already exist and will not delete
# the original file if copying fails for some reason.
#
# It DOES overwrite identical files in the destination directory
# with the ones in current, however.
#
# This script was originally written and put into
# Public Domain by Jarno Elonen <[email protected]> in June 2003.
# Feel free to do whatever you like with it.
# Defaults
TOOLS=(exiftool jq) # Also change settings below if changing this, the output should be in the format YYYY:MM:DD
DEFAULTDIR='/Users/jvhaarst/Pictures/van camera/van camera'
MAXDEPTH=-maxdepth 1
#MAXDEPTH=''
# activate debugging from here
#set -o xtrace
#set -o verbose
# Improve error handling
set -o errexit
set -o pipefail
# Check whether needed programs are installed
for TOOL in ${TOOLS[*]}
do
hash $TOOL 2>/dev/null || { echo >&2 "I require $TOOL but it's not installed. Aborting."; exit 1; }
done
# Enable handling of filenames with spaces:
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
# Use BASEDIR from commandline, or default if none given
BASEDIR=${1:-$DEFAULTDIR}
for FILE in $(find $(pwd -P) $MAXDEPTH -not -wholename "*._*" -iname "*.JPG" -or -iname "*.JPEG" -or -iname "*.CRW" -or -iname "*.THM" -or -iname "*.RW2" -or -iname '*.ARW' -or -iname "*AVI" -or -iname "*MOV" -or -iname "*MP4" -or -iname "*MTS" -or -iname "*PNG")
do
INPUT=${FILE}
DATE=$(exiftool -quiet -tab -dateformat "%Y:%m:%d" -json -DateTimeOriginal "${INPUT}" | jq --raw-output '.[].DateTimeOriginal')
if [ "$DATE" == "null" ] # If exif extraction with DateTimeOriginal failed
then
DATE=$(exiftool -quiet -tab -dateformat "%Y:%m:%d" -json -MediaCreateDate "${INPUT}" | jq --raw-output '.[].MediaCreateDate')
fi
if [ -z "$DATE" ] || [ "$DATE" == "null" ] # If exif extraction failed
then
DATE=$(stat -f "%Sm" -t %F "${INPUT}" | awk '{print $1}'| sed 's/-/:/g')
fi
if [ ! -z "$DATE" ]; # Doublecheck
then
YEAR=$(echo $DATE | sed -E "s/([0-9]*):([0-9]*):([0-9]*)/\\1/")
MONTH=$(echo $DATE | sed -E "s/([0-9]*):([0-9]*):([0-9]*)/\\2/")
DAY=$(echo $DATE | sed -E "s/([0-9]*):([0-9]*):([0-9]*)/\\3/")
if [ "$YEAR" -gt 0 ] & [ "$MONTH" -gt 0 ] & [ "$DAY" -gt 0 ]
then
OUTPUT_DIRECTORY=${BASEDIR}/${YEAR}_${MONTH}_${DAY}
mkdir -pv ${OUTPUT_DIRECTORY}
OUTPUT=${OUTPUT_DIRECTORY}/$(basename ${INPUT})
if [ -e "$OUTPUT" ] && ! cmp -s "$INPUT" "$OUTPUT"
then
echo "WARNING: '$OUTPUT' exists already and is different from '$INPUT'."
else
echo "Moving '$INPUT' to $OUTPUT"
rsync -ah --progress "$INPUT" "$OUTPUT"
if ! cmp -s "$INPUT" "$OUTPUT"
then
echo "WARNING: copying failed somehow, will not delete original '$INPUT'"
else
rm -f "$INPUT"
fi
fi
else
echo "WARNING: '$INPUT' doesn't contain date."
fi
else
echo "WARNING: '$INPUT' doesn't contain date."
fi
done
# restore $IFS
IFS=$SAVEIFS
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment