This example is a layer 1 script to make a special “magic” directory in which image files will be converted automatically therein.
The full script:
local formats = { jpg = true, gif = true, png = true }
convert = {
delay = 0,
maxProcesses = 99,
action = function(inlet)
local event = inlet.getEvent()
if event.isdir then
-- ignores events on dirs
inlet.discardEvent(event)
return
end
-- extract extension and basefilename
local p = event.pathname
local ext = string.match(p, ".*%.([^.]+)$")
local base = string.match(p, "(.*)%.[^.]+$")
if not formats[ext] then
-- an unknown extenion
log("Normal", "not doing something on ."..ext)
inlet.discardEvent(event)
return
end
-- autoconvert on create and modify
if event.etype == "Create" or event.etype == "Modify" then
-- builds one bash command
local cmd = ""
-- do for all other extensions
for k, _ in pairs(formats) do
if k ~= ext then
-- excludes files to be created, so no
-- followup actions will occur
inlet.addExclude(base..'.'..k)
if cmd ~= "" then
cmd = cmd .. " && "
end
cmd = cmd..
'/usr/bin/convert "'..
event.source..p..'" "'..
event.source..base..'.'..k..
'" || /bin/true'
end
end
log("Normal", "Converting "..p)
spawnShell(event, cmd)
return
end
-- deletes all formats if you delete one
if event.etype == "Delete" then
-- builds one bash command
local cmd = ""
-- do for all other extensions
for k, _ in pairs(formats) do
if k ~= ext then
-- excludes files to be deleted, so no
-- followup actions will occur
inlet.addExclude(base..'.'..k)
if cmd ~= "" then
cmd = cmd .. " && "
end
cmd = cmd..
'rm "'..event.source..base..'.'..k..
'" || /bin/true'
end
end
log("Normal", "Deleting all "..p)
spawnShell(event, cmd)
return
end
-- ignores other events.
inlet.discardEvent(event)
end,
-----
-- Removes excludes when convertions are finished
--
collect = function(event, exitcode)
local p = event.pathname
local ext = string.match(p, ".*%.([^.]+)$")
local base = string.match(p, "(.*)%.[^.]+$")
local inlet = event.inlet
if event.etype == "Create" or
event.etype == "Modify" or
event.etype == "Delete"
then
for k, _ in pairs(formats) do
inlet.rmExclude(base..'.'..k)
end
end
end,
}
sync{convert, source="magicdir", recursive=false}
This creates a local table of all supported file formats. The file formats are used as keys.
local formats = { jpg=true, gif=true, png=true, }
Configures actions to be instant and there is unlimits the amount the conversion to be done at once. Well not unlimited but set the limit pretty high.
convert = {
delay = 0,
maxProcesses = 99,
This script uses the layer 1 inlet interface altough it greps only single events and not lists. It does this instead of layer 2 as it needs to do common operations for all kind of events.
action = function(inlet)
local event = inlet.getEvent()
Ignores directories. As using layer 1 it has to explicitly discard events it does not spawn actions for.
if event.isdir then
-- ignores events on dirs
inlet.discardEvent(event)
return
end
Uses Lua string patterns to extract the file extension from the rest - here called base.
-- extract extension and basefilename
local p = event.pathname
local ext = string.match(p, ".*%.([^.]+)$")
local base = string.match(p, "(.*)%.[^.]+$")
Looks the extension up in the formats table. This can be done, since formats are keys in that table. If not an image format it bails out.
if not formats[ext] then
-- an unknown extenion
log("Normal", "not doing something on ."..ext)
inlet.discardEvent(event)
return
end
Following actions will done on “Create” and “Modify” events.
-- autoconvert on create and modify
if event.etype == "Create" or event.etype == "Modify" then
This script builds a bash command using a string.
-- builds one bash command
local cmd = ""
It iterates for all image formats and excludes the one which is the source image.
-- do for all other extensions
for k, _ in pairs(formats) do
if k ~= ext then
This is a little trick. It creates Exclusions for the converted images. As this images are not placed in a target directory but right next to the source image in the source directory they would otherwise trigger Create actions as well.
-- excludes files to be created, so no
-- followup actions will occur
inlet.addExclude(base..'.'..k)
And for every image to be converted adds the calls to the arguments. It uses " || /bin/true "
to let the shell continue if one conversion fails. In that it chains the conversion with ‘&&’ they will be called sequentially.
if cmd ~= "" then
cmd = cmd .. " && "
end
cmd = cmd..
'/usr/bin/convert "'..
event.source..p..'" "'..
event.source..base..'.'..k..
'" || /bin/true'
And eventually it spawns the shell doing the conversions and is finished.
end
end
log("Normal", "Converting "..p)
spawnShell(event, cmd)
return
end
For deletions it does technically something similar, but it deletes all other file formats of the image.
-- deletes all formats if you delete one
if event.etype == "Delete" then
-- builds one bash command
local cmd = ""
-- do for all other extensions
for k, _ in pairs(formats) do
if k ~= ext then
-- excludes files to be deleted, so no
-- followup actions will occur
inlet.addExclude(base..'.'..k)
if cmd ~= "" then
cmd = cmd .. " && "
end
cmd = cmd..
'rm "'..event.source..base..'.'..k..
'" || /bin/true'
end
end
log("Normal", "Deleting all "..p)
spawnShell(event, cmd)
return
end
and not to forget to nicely discard all other events.
-- ignores other events.
inlet.discardEvent(event)
end,
collect is called when the conversions finished. It will remove the temporary excludes again.
-----
-- Removes excludes when convertions are finished
--
collect = function(event, exitcode)
local p = event.pathname
local ext = string.match(p, ".*%.([^.]+)$")
local base = string.match(p, "(.*)%.[^.]+$")
local inlet = event.inlet
if event.etype == "Create" or
event.etype == "Modify" or
event.etype == "Delete"
then
for k, _ in pairs(formats) do
inlet.rmExclude(base..'.'..k)
end
end
end,
And finally use the configuration to watch “magicdir”.
sync{convert, source="magicdir", recursive=false}