Table of Contents

BASH - Directories - Monitor a directory for changes - Using inotifywait

Install inotify-tools

sudo apt install inotify-tools

Test inotifywait

In a shell enter:

while true; do
  res=`inotifywait -r thedirtowatch/ --format %f`;
  echo "RESULT=$res";
done

returns:

Setting up watches.  Beware: since -r was given, this may take a while!
Watches established.

NOTE: The --format %f refers to the filename in the event.

  • -r, --recursive: Watch all sub-directories of any directories passed as arguments. Watches will be set up recursively to an unlimited depth.
    • Symbolic links are not traversed. Newly created sub-directories will also be watched.

See http://manpages.ubuntu.com/manpages/focal/man1/inotifywait.1.html for options.


In a 2nd shell, go to that directory being watched.

cd thedirtowatch/
touch test1

NOTE: Back on the 1st shell this should show you output:

RESULT=test1

Only listen for certain events

Change the inotifywait to the following:

while true; do
  res=`inotifywait -q -e create, open, close, modify, moved_to, moved_from -r thedirtowatch/ --format '%e %f'`;
  echo "RESULT=$res\n";
done

NOTE: The additional -e option can be added to the inotifywait to only listen for certain events.

Events include:

  • access: A watched file or a file within a watched directory was read from.
  • modify: A watched file or a file within a watched directory was written to.
  • attrib: The metadata of a watched file or a file within a watched directory was modified.
    • This includes timestamps, file permissions, extended attributes etc.
  • close_write: A watched file or a file within a watched directory was closed, after being opened in writeable mode.
    • This does not necessarily imply the file was written to.
  • close_nowrite: A watched file or a file within a watched directory was closed, after being opened in read-only mode.
  • close: A watched file or a file within a watched directory was closed, regardless of how it was opened.
    • Note that this is actually implemented simply by listening for both close_write and close_nowrite, hence all close events received will be output as one of these, not CLOSE.
  • open: A watched file or a file within a watched directory was opened.
  • moved_to: A file or directory was moved into a watched directory.
    • This event occurs even if the file is simply moved from and to the same directory.
  • moved_from: A file or directory was moved from a watched directory.
    • This event occurs even if the file is simply moved from and to the same directory.
  • move: A file or directory was moved from or to a watched directory.
    • Note that this is actually implemented simply by listening for both moved_to and moved_from, hence all close events received will be output as one or both of these, not MOVE.
  • move_self: A watched file or directory was moved.
    • After this event, the file or directory is no longer being watched.
  • create: A file or directory was created within a watched directory.
  • delete: A file or directory within a watched directory was deleted.
  • delete_self: A watched file or directory was deleted.
    • After this event the file or directory is no longer being watched.
    • Note that this event can occur even if it is not explicitly being listened for.
  • unmount: The filesystem on which a watched file or directory resides was unmounted.
    • After this event the file or directory is no longer being watched.
    • Note that this event can occur even if it is not explicitly being listened to.

The --format option is changed to include showing %e which is the actual event. Obviously change as needed.

The -q option is to not show too much output.

See http://manpages.ubuntu.com/manpages/focal/man1/inotifywait.1.html for options.


Using monitor mode

Instead of running in a while true; do loop, an alternative is to use monitor mode:

inotifywait -m thedirtowatch/ -e create -e moved_to |
  while read dir action file; do
    echo "The file '$file' appeared in directory '$dir' via '$action'"
    # do something with the file.
  done

NOTE: The --format %f refers to the filename in the event.

  • -m, --monitor: Instead of exiting after receiving a single event, execute indefinitely.
    • The default behavior is to exit after the first event occurs.

See http://manpages.ubuntu.com/manpages/focal/man1/inotifywait.1.html for options.


Using a BASH Script

after-change.sh
#!/bin/bash
#
# Monitor the input directory and if any change occurs run the provided command:
#
# Usage:
#   after-change.sh /tmp ls -al %f
 
if [ $# -lt 3 ]; then
  echo "Usage: $0 dir cmd "
  exit 1
fi
 
which inotifywait 2>&1 >/dev/null
 
if [ "$?" == "1" ]; then
  echo "ERROR:  inotifywait not installed."
  exit 1
fi
 
dir=$1
shift
cmd=$1
shift
options=$*
 
inotifywait -q -r -m $dir $options
eval $cmd

References

http://manpages.ubuntu.com/manpages/focal/man1/inotifywait.1.html