Skip to content

Commit a6134bb

Browse files
committed
Add a script that renames all photo's and movies in a dir to date/time.
When photo's and movies from multiple sources are thrown in one dir it often becomes a mess of different file formats. Also it's impossible to view the images in chronological order. Very annoying when it's hundreds of holiday photo's of both my wife and me. This script searches for information about the date/time the photo/movie was taken/shot and renames the file to `date_time.ext`.
1 parent 31b7b96 commit a6134bb

File tree

1 file changed

+146
-0
lines changed

1 file changed

+146
-0
lines changed

order_photos_by_exif_date

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
#!/bin/bash
2+
# order_photos_by_exif_date
3+
4+
# When photo's from multiple sources are thrown into one directory it might
5+
# very well happen that the filenames screw the order. You see the serie of
6+
# camera one first, then the other.
7+
8+
# This renames all photo's to YYYYMMDD_HHMMSS.SubSec_DESCRIPTION_###.jpg by using the date from exif
9+
# information.
10+
#
11+
# The ### part is an optional random 3 digit number. If multiple photo's are
12+
# taken on the same time the serial will be incremented.
13+
14+
# CHANGELOG:
15+
# 2019-10-04 A.Swen created.
16+
17+
# SETTINGS
18+
date=$(date +%Y%m%d)
19+
me=$(basename $0)
20+
mydir=$(dirname $0)
21+
22+
# FUNCTIONS
23+
die () {
24+
rc=$1
25+
shift
26+
printf '%s\n' "=====================" >&2
27+
printf '%s\n' "==== FATAL ERROR ====" >&2
28+
printf '%s\n\n' "=====================" >&2
29+
printf '%s\n\n' "$@" >&2
30+
exit $rc
31+
}
32+
33+
usage () {
34+
printf '%s\n' "===============" >&2
35+
printf '%s\n' "==== USAGE ====" >&2
36+
printf '%s\n\n' "===============" >&2
37+
printf '%s\n' "Usage: ${me} [-d|--directory <directory>] [-D|--description <description>]" >&2
38+
printf '%s\n\n' "example: ${me} " >&2
39+
printf '%s\n\n' "example: ${me} -d /data/foto/bla -D 'A night at the opera'" >&2
40+
exit 1
41+
}
42+
get_options () {
43+
while [[ $# -gt 0 ]]; do
44+
case "$1" in
45+
--directory|-d)
46+
shift
47+
declare -r directory="$1"
48+
shift
49+
;;
50+
--description|-D)
51+
shift
52+
declare -r description="_${1}"
53+
shift
54+
;;
55+
-h|--help)
56+
usage
57+
;;
58+
*)
59+
usage
60+
;;
61+
esac
62+
done
63+
}
64+
65+
log () { printf '%s %s\n' "$(date +%F' '%T)" "$@"; }
66+
67+
# SCRIPT
68+
log "Started ${me}"
69+
70+
# Without exiftool we can't do much
71+
which exiftool 2>&1 > /dev/null || die 1 "Exiftool not found"
72+
which ffprobe 2>&1 > /dev/null || die 1 "Ffprobe not found"
73+
unset directory description
74+
75+
if [[ $# -gt 0 ]];then
76+
get_options
77+
fi
78+
[ -z "$directory" ] && directory="$(pwd)"
79+
[ -d "$directory" ] || die 2 "Directory '$directory' not found"
80+
81+
find "$directory" -iname \*.jpg -o -iname \*.jpeg -o -iname \*.dng -o -iname \*.mp4|while read original_filename;do
82+
83+
unset create_date_time
84+
85+
# Try to get the date/time from the file.
86+
case $original_filename in
87+
*.jpg|*.JPG|*.jpeg)
88+
create_date_time=$(exiftool -S -SubSecCreateDate "$original_filename"|sed -e 's?SubSecCreateDate: ??g' -e 's?:??g' -e 's? ?_?' -e 's?\.?_?g')
89+
if [ -z "$create_date_time" ];then
90+
# Try the DateTimeOriginal field
91+
create_date_time=$(exiftool -S -DateTimeOriginal "$original_filename"|sed -e 's?DateTimeOriginal: ??g' -e 's?:??g' -e 's? ?_?' -e 's?\.?_?g')
92+
fi
93+
if [ -z "$create_date_time" ];then
94+
# Try the GPSDateTime field
95+
unset gps_date_time
96+
gps_date_time=$(exiftool -S -GPSDateTime "$original_filename"|sed -e 's?GPSDateTime: ??' -e 's?:?-?' -e 's?:?-?' -e 's? ?T?')
97+
if [ -n "$gps_date_time" ];then
98+
create_date_time=$(date -d "$gps_date_time" +%Y%m%d_%H%M%S)
99+
fi
100+
fi
101+
if [ -z "$create_date_time" ];then
102+
# Try the FileModifyDate field
103+
file_modify_date=$(exiftool -S -FileModifyDate "$original_filename"|sed -e 's?FileModifyDate: ??' -e 's?:?-?' -e 's?:?-?')
104+
if [ -n "$file_modify_date" ];then
105+
create_date_time=$(date -d "$file_modify_date" +%Y%m%d_%H%M%S)
106+
fi
107+
fi
108+
ext=jpg
109+
;;
110+
*.dng|*.DNG)
111+
create_date_time=$(exiftool -S -DateTimeOriginal "$original_filename"|sed -e 's?DateTimeOriginal: ??g' -e 's?:??g' -e 's? ?_?' -e 's?\.?_?g') || die 4 "exiftool failed on $original_filename"
112+
ext=dng
113+
;;
114+
*.mp4|*MP4)
115+
create_date_time=$(date -d $(ffprobe "$original_filename" 2>&1 |grep creation_time|head -1|sed -e 's?\s\+creation_time\s\+:\s\+??') +%Y%m%d_%H%M%S)||die 5 "Cannot get creation_time from file $original_filename".
116+
ext=mp4
117+
;;
118+
*)
119+
log "I don't know how to get a date from $original_filename"
120+
continue
121+
;;
122+
esac
123+
124+
# If no create_date_time can be extracted we can't do much more.
125+
if [ -z "$create_date_time" ];then
126+
fn=$(basename "$original_filename")
127+
log "Can't find a date/time for $fn. We don't change it."
128+
unset fn
129+
continue
130+
fi
131+
132+
# With the information we have we can construct a new filename
133+
new_filename="$directory/${create_date_time}${description}.$ext"
134+
135+
# Check for duplicates. Should there be one: add a random number.
136+
until [ ! -f "$new_filename" ];do
137+
log "$new_filename exists, choosing new random serial."
138+
new_filename="$directory/${create_date_time}${description}_$((RANDOM % 999)).$ext"
139+
done
140+
141+
# Rename the file.
142+
echo Renaming \"$(basename "$original_filename")\" to \"$(basename "$new_filename")\"
143+
mv "$original_filename" "$new_filename"
144+
done
145+
146+
# END

0 commit comments

Comments
 (0)