I'm looking for a reliable way to detect renaming of files and get both old and new file names. This is what I have so far:
COUNTER=0;
inotifywait -m --format '%f' -e moved_from,moved_to ./ | while read FILE
do
if [ $COUNTER -eq 0 ]; then
FROM=$FILE;
COUNTER=1;
else
TO=$FILE;
COUNTER=0;
echo "sed -i 's/\/$FROM)/\/$TO)/g' /home/a/b/c/post/*.md"
sed -i 's/\/'$FROM')/\/'$TO')/g' /home/a/b/c/post/*.md
fi
done
It works, but it assumes you will never move files into or out of the watched folder. It also assumes that events come in pairs, first moved_from, then moved_to. I don't know if this is always true (works so far).
I read inotify uses a cookie to link events. Is the cookie accessible somehow?
Lacking the cookie, I thought about using timestamps to link events together. Any tips on getting FROM and TO in a more reliable way?
Best Answer
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 thestruct
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:This change modifies
libinotifytools.so
, not theinotifywait
binary. To test before installation: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.(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.)