Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
#!/usr/bin/env lua5.1
-- exifdatetime.lua - a library for handling and
-- classifying whiteboard images like this one:
--        http://angg.twu.net/2018.2-MD/20180813_MDA1.jpg
--   See: http://angg.twu.net/2018.2-MD/2018.2-MD.pdf
--        http://angg.twu.net/2018.2-MD.html
--        (find-angg ".emacs" "find-quadros-links")
--          
-- By Eduardo Ochs <eduardoochs@gmail.com>.
-- Version: 2018nov27. Public domain.
--          
-- «.fossils»		(to "fossils")
-- «.timeslots»		(to "timeslots")
-- «.courses»		(to "courses")
-- «.Year»		(to "Year")
-- «.ExifFile»		(to "ExifFile")
-- «.main-scripts»	(to "main-scripts")


-- «fossils» (to ".fossils")
getexifdatetime = function (fname)
    local bigstr = getoutput(format("exif %s | grep -i 'Date and time'", fname))
    local date,time = bigstr:match("([0-9:]+)%s+([0-9:]+)")
    if date then return date:gsub(":", ""), (time:gsub(":", "")) end
  end
getfnamedatecoursen = function (fname)
    local fname1 = fnamenondirectory(fname)
    local fdate,fcourse,fn = fname1:match("^([0-9]+)_([0-9A-Z]+)([0-9])%.")
    return fdate,fcourse,fn
  end

--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "exifdatetime.lua"
-- (find-fline "~/2018.2-MD/")
-- (find-fline "~/2018.2-MD/20180814_MDB1.jpg")
-- (find-exif  "~/2018.2-MD/20180814_MDB1.jpg")
= getexifdatetime     "~/2018.2-MD/20180814_MDB1.jpg"
= getfnamedatecoursen "~/2018.2-MD/20180814_MDB1.jpg"

--]]


-- «timeslots» (to ".timeslots")
inslot = function (time)
    return function (slot)
        local a0,c0 = slot:match("([0-9]+)-([0-9]+)")
        local b = time+0
        local a,c = a0*10000, c0*10000
        if a < b and b < c then return slot end
      end
  end
gettimeslot = function (time)
    local inslott = inslot(time - 3000)  -- 30 minutes
    return inslott "07-09" or
           inslott "09-11" or
           inslott "11-13" or
           inslott "14-16" or
           inslott "16-18"
  end

--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "exifdatetime.lua"
= gettimeslot(102345)  --> 09-11
= gettimeslot(112345)  --> 09-11
= gettimeslot(132345)  --> 11-13
= gettimeslot(142345)  --> nil
= gettimeslot(172345)  --> 16-18
= gettimeslot(182345)  --> 16-18
= gettimeslot(192345)  --> nil

--]]


-- «courses» (to ".courses")
-- (find-TH "2018.2")
courses = {}
-- courses["2a_11-13"] = "MDA"
-- courses["4a_11-13"] = "MDA"
-- courses["3a_16-18"] = "MDB"
-- courses["4a_14-16"] = "MDB"
-- courses["2a_16-18"] = "C2"
-- courses["4a_16-18"] = "C2"

-- (find-TH "2019.1")
-- courses["4a_11-13"] = "C2"
-- courses["6a_11-13"] = "C2"
-- courses["5a_09-11"] = "C3"
-- courses["6a_14-16"] = "C3"
-- courses["4a_16-18"] = "TD"
-- courses["6a_16-18"] = "TD"

-- (find-TH "2019.2")
courses["4a_11-13"] = "C2peq"
courses["6a_11-13"] = "C2peq"
courses["5a_11-13"] = "C2gde"
courses["6a_07-09"] = "C2gde"
courses["5a_14-16"] = "C3"
courses["6a_14-16"] = "C3"



-- «Year» (to ".Year")
-- A data structure that stores all days of a year and lets us
-- calculate weekdays. I wrote this because of the bug with 2018-11-14
-- in:
-- (find-es "unix" "date")
-- (find-es "unix" "date" "2018-11-04")
Year = Class {
  type = "Year",
  new  = function (yyyy, jan00, leap)
      local feb = leap and 29 or 28
      local dayofyear = {}
      local daysinmonth = {31, feb, 31, 30, 31, 30,
                           31,  31, 30, 31, 30, 31}
      for month=1,12 do
        for day=1,daysinmonth[month] do
          local mmdd = format("%02d%02d", month, day)
          table.insert(dayofyear, mmdd)
          dayofyear[mmdd] = #dayofyear
        end
      end
      return Year {year=yyyy, daysinmonth=daysinmonth, jan00=jan00,
                   dayofyear=dayofyear}
    end,
  __tostring = function (y)
      local y0=shallowcopy(y); y0.dayofyear="..."; return mytabletostring(y0)
    end,
  __index = {
    weekday = function (y, mmdd)
        local pat = y.year.."(%d%d%d%d)"
        if mmdd:match(pat) then mmdd = mmdd:match(pat) end
        return math.mod(y.dayofyear[mmdd]+y.jan00, 7)
      end,
    weekdayport = function (y, mmdd) return y:weekday(mmdd).."a" end,
  },
}

-- Initialize for 2018 and 2019:
-- 2018jan01 is a monday ("2a"): (ee-calendar-generate 1 2018)
-- 2018jan00 is a sunday ("1a"): (ee-calendar-generate 1 2018)
-- 2019jan00 is a monday ("2a"): (ee-calendar-generate 1 2019)
thisyear = Year.new(2018, 1)
thisyear = Year.new(2019, 2)

--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "exifdatetime.lua"
thisyear = Year.new(2018, 1)
PPV(thisyear.dayofyear)
= thisyear
= thisyear:weekdayport(    "1127")
= thisyear:weekdayport("20181127")
= thisyear:weekdayport("0101")

--]]



-- «ExifFile» (to ".ExifFile")
-- Usage: 
--   ef = ExifFile.new "~/2018.2-MD/20180814_MDB1.jpg"
--   print(ef.canonicalname)  --> 20180814_MDB_175210
--
ExifFile = Class {
  type = "ExifFile",
  new  = function (fname)
      return ExifFile({fname=fname}):runexif():getslot()
    end,
  __tostring = mytabletostring,
  __index = {
    runexif = function (ef)
        local cmd = format("exif %s | grep -i 'Date and time'", ef.fname)
        local bigstr = getoutput(cmd)
        ef.exifdatetime = getoutput(cmd)
        local date0,time0 = bigstr:match("([0-9:]+)%s+([0-9:]+)")
        if date0 then
          local date,time = date0:gsub(":", ""), time0:gsub(":", "")
          ef.date,ef.time = date, time
        end
        return ef
      end,  
    getslot = function (ef)
        ef.weekday = thisyear:weekdayport(ef.date)
        ef.timeslot = gettimeslot(ef.time) or ef.time
        ef.weekslot = ef.weekday.."_"..ef.timeslot
        ef.course = courses[ef.weekslot]
        if ef.course then
          ef.canonicalname = format("%s_%s_%s", ef.date, ef.course, ef.time)
        else
          ef.canonicalname = format("%s_%s", ef.date, ef.weekslot)
        end
        return ef
      end,
  },
}

--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "exifdatetime.lua"
= ExifFile.new "~/2018.2-MD/20180814_MDB1.jpg"
= ExifFile.new "~/2019.1-C2/20190320_C21.jpg"
= ExifFile.new "~/pergola/01_vista_do_203B.jpg"

# (find-fline "~/2018.2-MD/20180814_MDB1.jpg")

--]]





-- «main-scripts» (to ".main-scripts")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "exifdatetime.lua"
files = split(getoutput("ls ~/2019.2-C2/*C2*.jpg ~/2019.2-C3/*C3*.jpg"))
files = {}
files = split(getoutput("ls ~/2019.2-??/*.jpg"))
already = Set.new()   -- (find-angg "LUA/lua50init.lua" "Set")
for _,fname in ipairs(files) do
  local ef = ExifFile.new(fname)
  local cann = ef.canonicalname
  already:add(cann)
  print(fname, cann)
end
= already:ksc()

files = split(getoutput("ls /tmp/2019*.jpg"))
celular = Set.new()   -- (find-angg "LUA/lua50init.lua" "Set")
rms = ""
mvs = ""
for _,fname in ipairs(files) do
  local ef = ExifFile.new(fname)
  local cann = ef.canonicalname
  celular:add(cann)
  if already:has(cann) then
    rms = rms..format("rm -v "..fname.."\n")
  else
    mvs = mvs..format("mv -iv %s /tmp/%s.jpg\n", fname, cann)
  end
  -- print(fname, cann)
end
print(rms)
print(mvs)
writefile("/tmp/o", "\15 (eepitch-shell)\n"..rms..mvs)
-- (find-fline "/tmp/o")

-- Now rename the images, replacing the timestamps by serial numbers:
-- (find-fline "/tmp/")

PPV(files)
= already:ksc()


--]]