lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Newbie here, I needed a pretext to learn Lua, so I made a script which takes a bunch of image files and sorts them neatly into folders based on the EXIF timestamp of each file.

This whole thing can probably be done with exiv2 and some command-line kung-fu but, like I said, I needed a reason to write Lua code, so here it is.

Please see the script attached to this message and comment on any mistakes, idiosyncrasies, faux pas, etc.

Thanks,

--
Florin Andrei

http://florin.myip.org/
#!/usr/bin/lua

-- Using LuaFileSystem to manipulate files
require("lfs")

-- Locate exiv2 (the EXIF utility) using the shell
wout = io.popen("which exiv2", "r")
extool = wout:read()
wout:close()

if extool == nil then
    print("Cannot find the exiv2 utility. Bye bye.")
    return
end

-- Always require an argument
if table.maxn(arg) ~= 1 then
    print("\nimgsort - script to sort image files based on their EXIF timestamp attributes")
    print("by Florin Andrei, 2009/02/18")
    print("\nUsage: " .. arg[0] .. " <directory_containing_pictures>\n")
    return
end

dir = arg[1]

-- Run exiv2 on the directory with pictures
-- Capture the output in the bigtext table
excmd = io.popen(extool .. " " .. dir .. "/*", "r")
bigtext = {}
for line in excmd:lines() do
    table.insert(bigtext, line)
end
excmd:close()

-- Looking for lines like this: "work/IMG_0373.JPG Image timestamp : 2008:11:07 16:43:50"
-- Search pattern
patt_tail = "%s+Image timestamp%s+:%s+%d%d%d%d:%d%d:%d%d%s+%d%d:%d%d:%d%d"
-- Split pattern (extracting year, month and day)
cpatt_tail = "%s+Image timestamp%s+:%s+(%d%d%d%d):(%d%d):(%d%d)%s+%d%d:%d%d:%d%d"

-- Go through the list of files, retrieve dates
imagedates = {}
for l in lfs.dir(dir) do
    fn = dir .. "/" .. l
    
    patt = fn .. patt_tail
    cpatt = fn .. cpatt_tail

    -- In the big EXIF output, search for this file
    -- and the line with "Image timestamp"
    match = nil
    for i,exline in ipairs(bigtext) do
	if string.find(exline, patt) ~= nil then
	    -- Found it! Get the timestamp
	    match = exline
	    _, _, y, m, d = string.find(exline, cpatt)
	    break
	end
    end
    -- If valid date, then store file name and date in table
    if match ~= nil then
	imagedates[l] = y .. "-" .. m .. "-" .. d
    end
end

-- Find all distinct values for dates and store them
distdates = {}
for file,date in pairs(imagedates) do
    found = nil
    for i,d in ipairs(distdates) do
	if date == d then
	    found =1
	end
    end
    if found == nil then
	table.insert(distdates,date)
    end
end

-- Create a directory for each distinct date
for i,d in ipairs(distdates) do
    assert(lfs.mkdir(dir .. "/" .. d), "could not create directory " .. dir .. "/" .. d)
end

-- Move files in their respective directories, based on EXIF timestamp
for file,date in pairs(imagedates) do
    src = dir .. "/" .. file
    dst = dir .. "/" .. date .. "/" .. file
    assert(os.rename(src, dst), "could not move file " .. src .. " to " .. dst)
end