Skip to content

Instantly share code, notes, and snippets.

@chtzvt
Last active September 16, 2022 18:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chtzvt/b78fca8af2fb63aefd29d68bea98755d to your computer and use it in GitHub Desktop.
Save chtzvt/b78fca8af2fb63aefd29d68bea98755d to your computer and use it in GitHub Desktop.
Fixing missing/clobbered EXIF data on a portion of my photos library
# frozen_string_literal: true
require 'exif'
require 'fileutils'
require 'shellwords'
formats = ['.jpg', '.png', '.jpeg', '.mov', '.mp4', '.m4v']
def update_exif(year, month, day, f)
f = f.strip
filedir_exif_date = "#{year}:#{month}:#{day}"
fork do
system("exiftool '-AllDates=#{filedir_exif_date} 00:00:00' -overwrite_original #{Shellwords.escape(f)}")
end
end
Dir['./**/*'].each do |f|
next unless formats.include? File.extname(f.downcase)
match = %r{([0-9]{4})/([0-9]{2})/([0-9]{0,2})}.match(f)
unless match.nil?
file_year = match.captures[0]
file_month = match.captures[1]
file_day = match.captures[2]
end
begin
data = Exif::Data.new(File.open(f))
match = /([0-9]{4}):([0-9]{2}):([0-9]{0,2})/.match(data.date_time)
unless match.nil?
exif_year = match.captures[0]
exif_month = match.captures[1]
exif_day = match.captures[2]
end
unless exif_year === file_year && exif_month === file_month && exif_day === file_day
puts "Fixing date mismatch: #{f} (#{data.date_time} -> #{file_year}:#{file_month}:#{file_day})"
open('updated_files.log', 'a') do |log|
log.puts f
end
update_exif(file_year, file_month, file_day, f)
end
rescue Exif::NotReadable
puts "Couldn't read: #{f}"
open('unreadable.log', 'a') do |log|
log.puts f
end
rescue Exif::IFDNotFound
puts "IDF Not Found: #{f}"
open('idf_error.log', 'a') do |log|
log.puts f
end
rescue Exif::UnknownDataType
puts "Unknown Data Type #{f}!"
end
end
# frozen_string_literal: true
require 'shellwords'
def update_exif(year, month, day, f)
f = f.strip
filedir_exif_date = "#{year}:#{month}:#{day}"
puts "exiftool '-AllDates=#{filedir_exif_date} 00:00:00' -overwrite_original #{Shellwords.escape(f)}"
fork do
system("exiftool '-AllDates=#{filedir_exif_date} 00:00:00' -overwrite_original #{Shellwords.escape(f)}")
end
end
File.readlines('unreadable.log').each do |f|
f = f.strip
match = %r{([0-9]{4})/([0-9]{2})/([0-9]{0,2})}.match(f)
unless match.nil?
file_year = match.captures[0]
file_month = match.captures[1]
file_day = match.captures[2]
end
exiftool_out = `exiftool #{Shellwords.escape(f)}`
has_date_tag = exiftool_out.include? 'Date/Time Original'
has_create_date = exiftool_out.include? 'Create Date'
nulled_date = exiftool_out.include? 'Date/Time Original : 0000:00:00 00:00:00'
nulled_create_date = exiftool_out.include? 'Create Date : 0000:00:00 00:00:00'
# No date tags
unless has_date_tag || has_create_date
open('secondpass_updated.log', 'a') do |log|
log.puts f
end
update_exif(file_year, file_month, file_day, f)
end
# Nulled-out date/time tags
next unless nulled_date || nulled_create_date
open('secondpass_updated.log', 'a') do |log|
log.puts f
end
update_exif(file_year, file_month, file_day, f)
end
echo "Removing duplicate files..."
fdupes -r -d -N .
echo "Sorting..."
# Use -r for recursive sorting
exiftool -preserve -d '%Y/%m/%d/' "-directory<filemodifydate" "-directory<createdate" "-directory<datetimeoriginal" ./*.*
echo "Cleaning empty directories..."
find . -empty -type f -delete && find . -empty -type d -delete
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment