Thursday, October 8, 2009

Filesystem Based Events with Incron

Ok, so I installed and configured incron witch is a nice cron like system for subscribing to file system events such as file creation or modification. It works great with jobs like this:

/mydir/processing IN_CLOSE_WRITE mv $@/$# $@/../done


This line will look for new files written to /mydir/processing/ and move them to /mydir/done when they are finished witting and closed. (Won't work for log-type files that are kept open but there are other options for that.)

However you cant do either of the following things:

/mydir/processing/file*.txt IN_CLOSE_WRITE mv $@/$# $@/../done
/mydir/processing IN_CLOSE_WRITE cd $@ && ../proc_file $# && rm $#


The first example tried to monitor only a subset of the directory witch doesn't work. (Though you can monitor a single file by name.) The second example tries to execute a series bash operations on the file witch doesn't work. (Only one command can be executed, with no popping support.)

Both of these problems can be solved by writing a external bash file and calling that instead and passing it the file name like so.

/mydir/processing IN_CLOSE_WRITE myscript $#


But alas I'd prefer to not have hundreds of bash scripts and have the same capabilities for piping and concatenation that cron has. As it tunes out, after a few hours of screwing with it, two simple shell scripts will solve both these problems. With those two scripts installed the follwing command will work.

/mydir/processing IN_CLOSE_WRITE run filter $# ^*txt$ && cd $@ && ../proc_file $# && rm $#


In this case the run option will pass the rest of the line on to bash for full fledged execution. As the first step in the execution it will run the filter operation witch will return true if the filename matches the regex sting and continue execution or return false if not and end the command.

/usr/bin/run
#!/bin/bash
eval $@

/usr/bin/filter
#!/bin/bash
if [[ "$1" =~ $2 ]]; then
exit 0;
else
exit 1;
fi