2

I need to monitor a large list of files for deletion or movement. And this list can change dynamically quite a number of times. Is it possible to change the paths to watch of the FSEventStreamContext while the monitoring is in progress?

Is there any other better way to achieve this instead of using FSEvents.

Shanti K
  • 2,873
  • 1
  • 16
  • 31

1 Answers1

3

You can also use GCD dispatch sources to observe filesystem events.
An advantage over the (older) FSEvents API is, that dispatch sources notify via block-based handlers.

You can also specify a mask for the events that you are interested in (e.g. DISPATCH_VNODE_DELETE|DISPATCH_VNODE_RENAME for renames and deletions)

    NSURL* url = [NSURL fileURLWithPath:[@"~/Desktop/test.txt" stringByExpandingTildeInPath]];
    dispatch_queue_t observerQueue = dispatch_queue_create("filesystem-observer-queue", 0);
    int fileDescriptor = open([url fileSystemRepresentation], O_EVTONLY);
    dispatch_source_vnode_flags_t eventMask = DISPATCH_VNODE_DELETE|DISPATCH_VNODE_RENAME;
    dispatch_source_t fileSystemSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, fileDescriptor, eventMask, observerQueue);
    dispatch_source_set_event_handler(fileSystemSource, ^{
        dispatch_source_vnode_flags_t eventSourceFlag = dispatch_source_get_data(fileSystemSource);
        if(eventSourceFlag & DISPATCH_VNODE_DELETE)
        {
            NSLog(@"delete");
            dispatch_source_cancel(fileSystemSource);
        }
        else if(eventSourceFlag & DISPATCH_VNODE_RENAME)
        {
             NSLog(@"rename");
        }
        NSLog(@"Change at %@ of type %lu", url, eventSourceFlag);
    });
    dispatch_source_set_cancel_handler(fileSystemSource, ^{
        close(fileDescriptor);
    });
    dispatch_resume(fileSystemSource);

Some notes:

  • The above code just shows the general idea. It does not try to cover all edge cases.
  • When you observe a directory, you only get one notification that something changed, but no information about the affected file(s) or the change type.
  • DISPATCH_VNODE_DELETE means true deletion (e.g. not the Finders move to trash)
Thomas Zoechling
  • 34,177
  • 3
  • 81
  • 112
  • I might have to monitor around 500 files located in different locations.. is it possible via a single source? and also as i mentioned in the question, if it is possible by a single source, is it possible to change the list of files while the monitoring is in progress? – Shanti K Apr 08 '14 at 08:23
  • No. If the files to observe don't share a common parent directory, you'd need dedicated sources for each file. I don't know if there is a hard limit for dispatch sources or if it is advisable to use them for >500 files. You'll need to research/experiment :) – Thomas Zoechling Apr 08 '14 at 08:40
  • For some reason this isn't working for me I have made a file in my desktop called `test.txt`, put your code in a function, called onviewdidload, and deleted `test.txt` but no `NSLog(@"delete");` is being called?! – maxisme Oct 05 '15 at 10:42