Last active
December 12, 2022 22:02
-
-
Save jvhaarst/2343281 to your computer and use it in GitHub Desktop.
Bash script to move images, based on exif data and file timestamp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 <elonen@iki.fi> 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 |
Is 69 line correct or should be:
mkdir -pv ${OUTPUT_DIRECTORY} ?
Yeah, fixed now.
If $INPUT-Path equals $OUTPUT-Path you're just deleting the files.
Meaning if you run this script twice you delete all files which are already sorted.
Thanks for this script! I needed to modify lines 48 and 51 adding .val to make it work. Not sure why, probably my exiftool version (brew in osx el capitan)
DATE=$(exiftool -quiet -tab -dateformat "%Y:%m:%d" -json -DateTimeOriginal "${INPUT}" | jq --raw-output '.[].DateTimeOriginal.val')
Thanks for this 👍
Thanks for script ! How to also rename files based on some EXIF parameters like Nikon ShutterCount, Canon filenumber, etc. Thanks a lot
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Nice, thank you. This script uses
exiftool
as dependency, sobrew install exiftool
for mac people.