Automate your shell scripts using inotify and inotifywait

Everybody has some utility scripts and bash lines which help in the daily business as a developer.
Imagine a life without “Remove all .svn directories from a path“, “Find duplicate files and remove them“ or “Watermark a PDF file”.
How about a script which does this automatically? How to write a poor man’s IFTTT in a few lines!

The bash script: watermark a PDF

Using pdftk it’s very easy to watermark (e.g. add a corporate letterhead to a PDF) an existing file:

#!/bin/bash
INFILE=$1
OUTFILE=$2

BACKGROUND=data/letterhead.pdf
if [ $# -eq 2 ]; then
pdftk "$INFILE" stamp $BACKGROUND output "$OUTFILE" allow printing compress
else
echo "Two parameters are required. (1. input pdf 2. resultfile)"
fi

You can invoke this script with an input file and an output file name, and the new file will get a Stamp / Watermark / Background image and will be saved to the output file path.

Excellent, this script works very well – but everytime you want to polish your PDFs you will have to remember the script name and the parameters. We should automate it.

Automation using cron

To automate the behaviour, add a cron job which executes this script for all new files inside a directory.

The script watermark_all.sh is called by cron every minute, watches for new pdf files inside a directory, watermarks them and starts over again in one minute.

#!/bin/bash

WORKINGDIR=/home/user/pdfs

cd $WORKINGDIR
mkdir -p naked

for file in *.pdf; do
if [ $file == "*.pdf" ]; then
break
fi
newfile=${file/.pdf/-BP.pdf}
./watermark_script.sh "$file" "$newfile";

mv "$file" naked
mv "$newfile" ../
done;

This works, but usually, you want your file converted just now and not in a few minutes.

Best solution for instant results: inotifywait

Most of the time, the script from above has pointless effort. There will be no new files, but, in the moment there are new files, it will take 30s to detect the change on average.

Inotify is a great way to monitor file system changes, and with the great tool inotifywait ( found in inotify-tools package in Ubuntu) it’s even utilizeable in Bash scripts.

#!/bin/bash
while true; do

inotifywait -e create /home/user/pdfs  && \
./watermark_all.sh

done

Inotifywait creates an inotify watch on the directory /home/user/pdfs and waits until a file is created. In this event, inotifywait terminates and the ./watermark_all.sh script from above will be executed.

Great – Immediate results :-)

Automate your daily business

Use inotifywait for nearly everything scriptable! Check your JavaScript files with JSLint/JSHint right upon the save or even start analyzing your log files just after a log rotation. If you want to gather file system statistics really fast and easy, have a look at inotifywatch. You will see what happens inside a directory on a file system call level.

Tip: If you want to automate your cloud folders, have a look at wappwolf.com, they offer a similar approach inside the cloud using many different file conversion apps.

This entry was posted in General and tagged , , , . Bookmark the permalink.

12 Responses to Automate your shell scripts using inotify and inotifywait

  1. Sebastian Andersson says:

    What if the new file was created before inotifywait starts?

    Perhaps this works better?

    (echo start; inotifywait -m -e create /home/user/pdfs) |
    while read file; do
    ./watermark_all.sh;
    done

    The extra echo is needed to run watermark_all.sh when this is first started.

    • actually, the code used in production adds a ./watermark_all.sh just before the loop. I omitted it for clarity. Thanks for pointing this out!

  2. webreac says:

    Your example has a race condition problem if a file is created during the watermarking. You should leave inotifywait outside of the loop using the -m options.

    Something like (not tested):
    inotifywait -m -e create /home/user/pdfs | while read line ; do pdftk “$line” stamp data/letterhead.pdf output another_dir/”$line” allow printing compress ; done

    • Thanks for the input – I will have a deeper look into the monitor mode of inotifywait.

      Additionally, I’ve missed the “move_to”, as files moved inside the watched directory don’t get “created”.
      To add this event, simple invoke inotifywait with -e create,move_to

  3. This is an interesting idea for PDFs. I might suggest it would be more manageable to use approaches like Cacti for logs and commit hooks for JSLint or other development tasks like running test suite or

  4. SxDx says:

    stop with auto-popup and moving crappy “try me” shit, it’s disturbing

  5. Chris Laskey says:

    Hey Gregor, thanks for the post. Informative and to the point.

    One way to improve the code would be to use the inotifywait command’s –monitor flag. It keeps the inotifywait command alive instead of exiting after the first event without having to use an external “while true; do” loop.

  6. Pingback: Linux: Using inotify and inotifywait to automate shell scripts - Benohead's Software Blog | Benohead's Software Blog

  7. Pingback: URL

  8. Helen Neely says:

    Thanks for this example on how to use the inotify. It’s given me ideas on a pet project :)