http://www.perlmonks.org?node_id=974576


in reply to inotify problem

Same here (SuSE 11.4, Perl 5.14.1, Linux::Inotify2 V1.22) - works.

As AM already said, it depends on how you change the file and if you rename the original file during the process. Try the following changes, run stat file_to_watch before and after your experiment.

## my $w = $notify->watch ($file_to_watch, IN_MODIFY, \&on_change) or + die $!; my $w = $notify->watch ($file_to_watch, IN_MODIFY | IN_MOVE_SELF, +\&on_change2) or die $!; ... sub on_change2 { my($e) = @_; print $e->fullname, " changed "; print " and also moved!" if $e->IN_MOVE_SELF; print "\n"; }

E.g., if I mix edit the file using Emacs and echo, the program stops reporting changes. If I append to the Emacs backup file (file_to_watch~) the modifications are reported again. The original file is watched, regardless of the fact that it has been renamed.

You could monitor the (file-name-)changes (IN_MOVE_SELF) and just re-init the watcher to keep track of further changes applied to the file identified by its name, not by its inode.

Replies are listed 'Best First'.
Re^2: inotify problem
by morgon (Priest) on Jun 05, 2012 at 22:25 UTC
    Thanks for the suggestions, the problem is that when you get the event that the file has moved the copy does not yet exist (preventing a new watch), so you need to watch the directory as well...

    Here what seems to work for me, any improvements welcome:

    use strict; use Linux::Inotify2; use File::Basename qw(dirname); use File::Spec; $|++; my ($file_to_watch)=@ARGV; my $notify = Linux::Inotify2->new or die $!; &setup_watch; sub setup_watch { $notify->watch ($file_to_watch, IN_MODIFY | IN_MOVE_SELF, \&watch_fi +le) or die $!; } sub watch_file { my($e)=@_; my $fn = $e->fullname; if($e->IN_MODIFY) { print "$fn changed\n"; } if($e->IN_MOVE_SELF) { print "old $fn moved\n"; $e->w->cancel; my $dir = dirname $fn; $notify->watch ($dir, IN_CREATE, \&watch_dir) or die $!; } } sub watch_dir { my($e)=@_; my $fn = File::Spec->canonpath($e->fullname); return unless $fn eq $file_to_watch; $e->w->cancel; print "$fn newly created (probably changed)\n"; setup_watch; } while(1) { my $n = $notify->poll; print "handled $n events\n\n"; }