ivo Welch
ivo Welch

Reputation: 2876

watching files for changes with perl (macos and linux)

I would like to watch a set of files for changes, and do so without a large CPU and battery penalty. Ideally, my perl code would run on both macos and linux, but the former is more important. I tried

I tried Mac::FSEvents, which works on macos and seems to do nicely for directories, but not for files as far as I can tell.

my $fs = Mac::FSEvents->new('try.txt');
my $fh= $fs->watch;

my $sel = IO::Select->new($fh);
while ( $sel->can_read ) {
  my @events = $fs->read_events;
  for my $event ( @events ) {
    printf "File %s changed\n", $event->path;
  }
}

which simply does not respond; and the promisingly more OS agnostic

use File::Monitor;
my $monitor = File::Monitor->new();

my @files= qw(try.txt);

foreach (@files) { $monitor->watch($_); }

which consumes 100% CPU. the $monitor-watch() alone does not block. I also tried

use File::Monitor;
my $monitor = File::Monitor->new();

$monitor->watch('try.txt', sub {
                  my ($name, $event, $change) = @_;
                  print "file has changed\n";
                });

but this immediately returns.

I found another,

use File::ChangeNotify;

my $watcher =
  File::ChangeNotify->instantiate_watcher
  ( directories => [ './' ],
    filter      => qr/try\.txt/,
  );

# blocking
while ( my @events = $watcher->wait_for_events() ) {
  print "file has changed\n";
}

but the CPU utilization is again high (70%).

Maybe these are all the wrong cpan modules, too. could someone please give me advice on how I should do this?

regards,

/iaw

Upvotes: 0

Views: 380

Answers (1)

ivo Welch
ivo Welch

Reputation: 2876

Partial (macos-specific) example:

use IO::Select;
use Mac::FSEvents;
my $fs = Mac::FSEvents->new(
    path          => ['./try.txt', './try2.txt'],
    file_events   => 1,
    );

my $fh= $fs->watch;
my $sel = IO::Select->new($fh);
while ( $sel->can_read ) {
  my @events = $fs->read_events;
  for my $event ( @events ) {
    printf "File %s changed\n", $event->path;
  }
}

(i.e., it needed the file_events flag.)

Upvotes: 1

Related Questions