#!/usr/bin/env ruby require 'date' $possible_devices = { "SIGMA DP2 Merrill" => "dp2m", "FP2" => "fp2", "Canon EOS 1000D" => "1000d", "iPad Air" => "ipadair", "iPhone 5s" => "iphone5s", "iPhone SE" => "iphonese", "IQ180" => "iq180", "iPhone XR" => "iphonexr", "NIKON D70" => "d70" } $possible_devices.default = "unknown-device" file_ext = ARGV[0] if !file_ext file_ext = "jpg" end if ARGV[1] $possible_devices.default = ARGV[1] end ids = [] while line = STDIN.gets # list of files a = line.split('.') a.pop ids << a.join('.') end used_prefixes = {} # prefix -> 0..N def parse_timestamp s d = s.split(':', 2)[1] d.strip! d.gsub!(/^(\d\d\d\d):(\d\d):(\d\d)/, "\\1-\\2-\\3") return DateTime.parse d end def determine_datetime dts, subsec=nil dt = dts.min # get the actual original date if subsec != nil and subsec.to_i > 0 # add sub-seconds if available if dt.strftime("%L") == "000" s = format_datetime(dt)+".#{subsec}" dt = DateTime.parse s end end return dt end def format_datetime dt if dt.strftime("%L") == "000" return dt.strftime("%Y-%m-%dT%H:%M:%S") else return dt.strftime("%Y-%m-%dT%H:%M:%S.%L") end end def get_possible_device s s.strip! s.downcase! $possible_devices.each { |k,v| if s.downcase.start_with? k.downcase return v end } return $possible_devices.default end def parse_device s d = s.split(':', 2)[1] return get_possible_device d end def determine_device a a.each { |s| if s != $possible_devices.default return s end } return $possible_devices.default end ids.each do |i| exif = `exiftool "#{i}.#{file_ext}" 2>/dev/null` a = exif.split "\n" timestamps = [] subsec_time = nil devices = [] a.each { |j| if j.start_with? "Camera Model Name" \ or j.start_with? "Model" \ or j.start_with? "Lens Model" devices << parse_device(j) elsif j.start_with? "Date/Time Original" \ or j.start_with? "Creation Date" \ or j.start_with? "Create Date" \ or j.start_with? "Media Create Date" \ or j.start_with? "Track Create Date" \ or j.start_with? "File Modification Date/Time" begin timestamps << parse_timestamp(j) rescue end elsif j.start_with? "Sub Sec Time Original" subsec_time = j.split(':', 2)[1].strip end } if timestamps.size == 0 puts "No timestamp found" exit end skip = false new_prefix = "" add = 0 begin t = format_datetime(determine_datetime(timestamps, subsec_time)) d = determine_device devices new_prefix = "#{t}-#{d}" add = 1 rescue puts "Cannot determine metadata for #{i}, skipping!" skip = true end next if skip while used_prefixes.has_key? new_prefix new_prefix = "#{t}-#{add}-#{d}" add += 1 end used_prefixes[new_prefix] = true Dir.glob("#{i}*").each { |f| ext = f.sub("#{i}","") if File.exists? "#{new_prefix}#{ext}" puts "File exists: #{new_prefix}#{ext} (#{i})!" exit else `mv \"#{i}#{ext}\" #{new_prefix}#{ext}` end } end