Question

Is it possible to see which files have been changed whenever an change-event is called using: https://metacpan.org/pod/Mac::FSEvents ?

Thanks a lot! :)

Was it helpful?

Solution

File System Events API was designed to mirror large tree of files changes, if you want to mirror particular file changes you might be better of with IO::KQueue. The perl binding is missing a few constant for event flags, but you can obtain these from File System Events Programming Guide.

This script should get you started, it prints out any file events in '/path'

#!/usr/bin/perl
use strict;
use warnings;

use IO::Select    qw[];
use Mac::FSEvents qw[FILE_EVENTS];

my $fse = Mac::FSEvents->new({
    path  => '/path',
    flags => FILE_EVENTS
});

my $select = IO::Select->new($fse->watch);

# http://developer.apple.com/library/mac/#documentation/Darwin/Reference/FSEvents_Ref/FSEvents_h/index.html#//apple_ref/c/tag/FSEventStreamEventFlags
my %names = reverse (
    kFSEventStreamEventFlagNone              => 0x00000000,
    kFSEventStreamEventFlagMustScanSubDirs   => 0x00000001,
    kFSEventStreamEventFlagUserDropped       => 0x00000002,
    kFSEventStreamEventFlagKernelDropped     => 0x00000004,
    kFSEventStreamEventFlagEventIdsWrapped   => 0x00000008,
    kFSEventStreamEventFlagHistoryDone       => 0x00000010,
    kFSEventStreamEventFlagRootChanged       => 0x00000020,
    kFSEventStreamEventFlagMount             => 0x00000040,
    kFSEventStreamEventFlagUnmount           => 0x00000080,
    kFSEventStreamEventFlagItemCreated       => 0x00000100,
    kFSEventStreamEventFlagItemRemoved       => 0x00000200,
    kFSEventStreamEventFlagItemInodeMetaMod  => 0x00000400,
    kFSEventStreamEventFlagItemRenamed       => 0x00000800,
    kFSEventStreamEventFlagItemModified      => 0x00001000,
    kFSEventStreamEventFlagItemFinderInfoMod => 0x00002000,
    kFSEventStreamEventFlagItemChangeOwner   => 0x00004000,
    kFSEventStreamEventFlagItemXattrMod      => 0x00008000,
    kFSEventStreamEventFlagItemIsFile        => 0x00010000,
    kFSEventStreamEventFlagItemIsDir         => 0x00020000,
    kFSEventStreamEventFlagItemIsSymlink     => 0x00040000
);

use constant kFSEventStreamEventFlagItemIsFile => 0x00010000;

while ($select->can_read) {
    for my $event ($fse->read_events) {
        my $flags = $event->flags;
        my @names;

        next unless $flags & kFSEventStreamEventFlagItemIsFile;

        while ((my $flag = $flags & -$flags) != 0) {
            push @names, $names{$flag} || sprintf '0x%.8X';
            $flags &= ~$flag;
        }

        printf qq['%s': %s\n], $event->path, join ' | ', @names;
    }
}
$fse->stop;

Example events:

$ echo foo > foo.txt
'/path/foo.txt': kFSEventStreamEventFlagItemCreated | kFSEventStreamEventFlagItemModified | kFSEventStreamEventFlagItemIsFile

$ touch foo.txt
'/path/foo.txt': kFSEventStreamEventFlagItemInodeMetaMod | kFSEventStreamEventFlagItemIsFile

$ echo foo >> foo.txt
'/path/foo.txt': kFSEventStreamEventFlagItemModified | kFSEventStreamEventFlagItemIsFile

$ mv foo.txt bar.txt
'/path/foo.txt': kFSEventStreamEventFlagItemRenamed | kFSEventStreamEventFlagItemIsFile
'/path/bar.txt': kFSEventStreamEventFlagItemRenamed | kFSEventStreamEventFlagItemIsFile

$ rm bar.txt
'/path/bar.txt': kFSEventStreamEventFlagItemRemoved | kFSEventStreamEventFlagItemIsFile
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top