-
Notifications
You must be signed in to change notification settings - Fork 1
/
imagedate.sh
269 lines (229 loc) · 8.53 KB
/
imagedate.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
#!/bin/bash
# ---------------------------------------------------------------------------
# imagedate - Rewrite file and metadata dates on images to increment in the
# order of the alphabetized filenames.
#
# I had a directory of images that were alphabetized by filename, and I wanted
# to import them into Snapfish. I wanted to order them by filename, but
# Snapfish only offered sorting by the date the photos were taken (forward or
# back).
#
# So I went about finding out how to create sequential creation dates for these
# photos' metadata based on their alphabetized file names. Date and time of
# first image is customizable (default 2000:01:01 00:00:00) and images are
# separated in increments of 5 minutes.
#
# This script requires exiftool to be installed: https://exiftool.org
# Copyright 2021, Ivan Boothe <git@rootwork.org>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License at <http://www.gnu.org/licenses/> for
# more details.
# USAGE
#
# $ ./imagedate.sh [-q|--quiet] [--date=<YYYY:mm:ss>] [--time=<HH:MM:SS>] <DIR>
# $ ./imagedate.sh [-h|--help]
# EXAMPLES
#
# $ ./imagedate.sh .
# $ ./imagedate.sh -q images
# $ ./imagedate.sh --date="2020:01:01" --time="10:10:10" images
# $ ./imagedate.sh -q --date="2020:01:01" --time="10:10:10" images
# $ ./imagedate.sh --help
# HELPFUL COMMANDS
# Additional tools you can use during this process.
#
# check file dates
# $ stat <FILE>
#
# check EXIF dates
# $ exiftool <FILE> | grep "Date"
#
# check EXIF dates and get relevant field parameters
# $ exiftool -a -G0:1 -time:all <FILE>
#
# clean up exiftool "_original" files if you've generated them
# $ exiftool -delete_original <DIR>
#
# show EXIF problems for an individual file or all files in a directory
# $ exiftool -validate -error -warning -a -r <FILE/DIR>
# RESOURCES
#
# https://askubuntu.com/questions/62492/how-can-i-change-the-date-modified-created-of-a-file
# https://www.thegeekstuff.com/2012/11/linux-touch-command/
# https://unix.stackexchange.com/questions/180315/bash-script-ask-for-user-input-to-change-a-directory-sub-directorys-and-file
# https://photo.stackexchange.com/questions/60342/how-can-i-incrementally-date-photos
# https://exiftool.org/forum/index.php?topic=3429.0
# Revision history:
# 2021-11-29 Updating license (1.4)
# 2021-10-15 Adding checks for dependencies, updates to notifications (1.3)
# 2021-10-14 Added flag options for date and time; applying quiet mode to
# exiftool; minor cleanup and bug fixes (1.2)
# 2021-10-13 Modified into a full-fledged program (1.1)
# 2020-12-02 Created as a GitHub Gist of suggested commands
# ---------------------------------------------------------------------------
# Standard variables
PROGNAME=${0##*/}
VERSION="1.4"
red=$(tput setaf 1)
green=$(tput setaf 2)
yellow=$(tput setaf 3)
cyan=$(tput setaf 6)
bold=$(tput bold)
reset=$(tput sgr0)
# Error handling
error_exit() {
local error_message="${red}$1${reset}"
printf "%s\n" "${PROGNAME}: ${error_message:-"Unknown Error"}" >&2
exit 1
}
graceful_exit() {
exit 0
}
signal_exit() {
local signal="$1"
case "$signal" in
INT)
error_exit "${yellow}Program interrupted by user.${reset}"
;;
TERM)
printf "\n%s\n" "${red}$PROGNAME: Program terminated.${reset}" >&2
graceful_exit
;;
*)
error_exit "${red}$PROGNAME: Terminating on unknown signal.${reset}"
;;
esac
}
# Usage: Separate lines for mutually exclusive options.
usage() {
printf "%s\n" \
"${bold}Usage:${reset} ${PROGNAME} [-q|--quiet] [--date=<YYYY:mm:ss>] [--time=<HH:MM:SS>] <DIR>"
printf "%s\n" \
" ${PROGNAME} [-h|--help]"
}
# Help message for --help
help_message() {
cat <<-_EOF_
${bold}${PROGNAME} ${VERSION}${reset}
${cyan}
Rewrite file and metadata dates on images to increment in the order of the
alphabetized filenames. Useful when you have a system (Snapfish) that will
only order by date, but you want images ordered by filename. Date and time of
first image is customizable (default 2000:01:01 00:00:00) and images are
separated in increments of 5 minutes.${reset}
$(usage)
${bold}Options:${reset}
-h, --help Display this help message and exit.
-q, --quiet Quiet mode. Accept all defaults.
--date= Provide starting date, in YYYY:mm:dd format.
--time= Provide starting time, in HH:MM:SS format.
_EOF_
}
# Options and flags from command line
needs_arg() {
if [ -z "$OPTARG" ]; then
error_exit "Error: Argument required for option '$OPT' but none provided."
fi
}
while getopts :dt-:qh OPT; do
if [ "$OPT" = "-" ]; then
OPT="${OPTARG%%=*}" # extract long option name
OPTARG="${OPTARG#$OPT}" # extract long option argument (may be empty)
OPTARG="${OPTARG#=}" # remove assigning `=`
fi
case "$OPT" in
h | help)
help_message
graceful_exit
;;
q | quiet)
quiet_mode="-quiet"
;;
d | date)
needs_arg
date="$OPTARG"
;;
t | time)
needs_arg
time="$OPTARG"
;;
??*) # bad long option
usage >&2
error_exit "Unknown option --$OPT"
;;
?) # bad short option
usage >&2
error_exit "Unknown option -$OPTARG"
;;
esac
done
shift $((OPTIND - 1)) # remove parsed options and args from $@ list
# Program variables
dir=$1
if [[ ! $dir ]]; then
usage >&2
error_exit "Directory must be provided."
fi
[[ "$dir" =~ ^[./].*$ ]] || dir="./$dir"
# Dependencies
exiftool=$(command -v exiftool)
if [[ ! $exiftool ]]; then
error_exit "Exiftool must be installed <https://exiftool.org>. Aborting."
fi
if [ -d "${dir}" ]; then # Make sure directory exists
if [[ ! $quiet_mode ]]; then
printf "%s\n" "${bold}${red}WARNING:${reset}${bold} This script will overwrite file and metadata dates for any images it finds in the directory ${red}${dir}${reset}${bold} -- do you want to proceed? (y/N)${reset}"
read -r go
fi
if [[ $go == *"y"* || $quiet_mode ]]; then
if [[ ! $date ]]; then
if [[ ! $quiet_mode ]]; then
printf "%s\n" "${yellow}On what date do you want your images to begin incrementing (YYYY:mm:dd, default 2000:01:01)?${reset}"
read -r startdate
fi
date="${startdate:=2000:01:01}"
fi
if [[ ! $time ]]; then
if [[ ! $quiet_mode ]]; then
printf "%s\n" "${yellow}At what time do you want your images to begin incrementing (HH:MM:SS, default 00:00:00)?${reset}"
read -r starttime
fi
time="${starttime:=00:00:00)}"
fi
# Begin...
printf "%s\n" "${green}Setting image dates...${reset}"
# Set all files to sequential (alphabetical) modified date.
touch -a -m -- "${dir}"/* || error_exit "touch failed in line $LINENO"
# Now space them apart to ensure crappy photo software picks up on the
# differences.
for i in "${dir}"/*; do
touch -r "$i" -d '-1 hour' "$i" || error_exit "touch failed in line $LINENO"
sleep 0.005
done
# Use exiftool to set "all dates" (which is only standard image
# creation/modification/access) to an arbitrary date, (P)reserving file
# modification date.
$exiftool $quiet_mode -overwrite_original -P -alldates="${date} ${time}" "${dir}"/. || error_exit "exiftool failed in line $LINENO"
# Now update those dates sequentially separated apart (timestamps will kick
# over to the next day/month/year as necessary), going alphabetically by
# filename, at five-minute intervals.
$exiftool $quiet_mode -fileorder FileName -overwrite_original -P '-alldates+<0:${filesequence;$_*=5}' "${dir}"/. || error_exit "exiftool failed in line $LINENO"
# Update nonstandard "Date/Time Digitized" field to match creation date.
$exiftool $quiet_mode -r -overwrite_original -P "-XMP-exif:DateTimeDigitized<CreateDate" "${dir}"/. || error_exit "exiftool failed in line $LINENO"
# Update nonstandard and stupidly vague "Metadata Date" field to match
# creation date.
$exiftool $quiet_mode -r -overwrite_original -P "-XMP-xmp:MetadataDate<CreateDate" "${dir}"/. || error_exit "exiftool failed in line $LINENO"
printf "%s\n" "${green} ...done.${reset}"
else
printf "%s\n" "${yellow}Operation canceled.${reset}"
graceful_exit
fi
else
error_exit "Directory '${dir}' not found."
fi