I think your approach is correct, and tracking the cookie is a robust way of doing this.
However, the only place in the source of inotify-tools (3.14) that cookie
is referenced is in the header defining the struct
to match the kernel API.
If you like living on the edge, this patch (issue #72) applies cleanly to 3.14 and adds a %c
format specifier for the event cookie in hex:
--- libinotifytools/src/inotifytools.c.orig 2014-10-23 18:05:24.000000000 +0100
+++ libinotifytools/src/inotifytools.c 2014-10-23 18:15:47.000000000 +0100
@@ -1881,6 +1881,12 @@
continue;
}
+ if ( ch1 == 'c' ) {
+ ind += snprintf( &out[ind], size-ind, "%x", event->cookie);
+ ++i;
+ continue;
+ }
+
if ( ch1 == 'e' ) {
eventstr = inotifytools_event_to_str( event->mask );
strncpy( &out[ind], eventstr, size - ind );
This change modifies libinotifytools.so
, not the inotifywait
binary. To test before installation:
LD_PRELOAD=./libinotifytools/src/.libs/libinotifytools.so.0.4.1 \
inotifywait --format="%c %e %f" -m -e move /tmp/test
Setting up watches.
Watches established.
40ff8 MOVED_FROM b
40ff8 MOVED_TO a
Assuming that MOVED_FROM always occurs before MOVED_TO (it does, see fsnotify_move()
, and it's an ordered queue, though independent moves might get interleaved) in your script you cache the details when you see a MOVED_FROM line (perhaps in an associative array indexed by ID), and run your processing when you see a MOVED_TO with the matching half of the information.
declare -A cache
inotifywait --format="%c %e %f" -m -e move /tmp/test |
while read id event file; do
if [ "$event" = "MOVED_FROM" ]; then
cache[$id]=$file
fi
if [ "$event" = "MOVED_TO" ]; then
if [ "${cache[$id]}" ]; then
echo "processing ..."
unset cache[$id]
else
echo "mismatch for $id"
fi
fi
done
(With three threads running to shuffle a pair of files each 10,000 times, I never saw a single out of order event, or event interleaving. It may depend on filesystem and other conditions of course.)
how do I modify the inotifywait command to report only when a file of
certain type/extension is created
Please note that this is untested code since I don't have access to inotify
right now. But something akin to this ought to work:
inotifywait -m /path -e create -e moved_to |
while read path action file; do
if [[ "$file" =~ .*xml$ ]]; then # Does the file end with .xml?
echo "xml file" # If so, do your thing here!
fi
done
Best Answer
I assume you mean filenames that start with a dot (
.
), you can ignore those. The thing withinotifywait --exclude
is that the pattern appears to be matched against the full path of the file, so you'll need to take that into account.So, if you give
inotifywait
the directoriesfoo
andbar
to watch, then the patterns match against filenames likefoo/something
,bar/somethingelse
. As usual in regexes, you need to escape the dot.This should watch for all creates in the current directory except for dotfiles (it's a regex, so we need to escape the dots):
Or, less specifically, exclude dotfiles in any directories, by looking for the combination of a slash and dot:
That, of course, will not work if you're watching a directory with a leading dot in some part of the path; it'll match everything in that path.