summaryrefslogtreecommitdiff
path: root/rename-pix-by-time-and-cam
blob: 16f080879e315527b631ecf132cbfbcdbcb9dd13 (plain)
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
#!/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