отслеживание переименования / удаления файлов с помощью FSEvents на Lion - PullRequest
13 голосов
/ 04 сентября 2011

Я пытаюсь использовать FSEvents, чтобы определить, когда файлы были добавлены / удалены из определенной папки. На данный момент я реализовал простую оболочку для FSEvents, и она отлично работает: я получаю все события.

НО проблема, с которой я столкнулся сейчас, заключается в том, что когда я переименовываю файл в Finder, я ловлю 2 разных события: первое с типом «переименовано» со старым именем файла, а другое с «переименованным» и новым имя файла. Идентификаторы событий отличаются для обоих вызовов.

Итак, как мне узнать, какое "переименованное" событие содержит старое имя, а какое событие содержит старое ?? Я попытался посмотреть в документации, но, к сожалению, kFSEventStreamEventFlagItemRenamed не задокументирован ... он кажется новым в Lion.

PS: единственный способ, которым я мог придумать, был: при переименованном событии я проверяю свой интерфейс, чтобы увидеть, есть ли у меня элемент, соответствующий пути события. Если так, я отмечаю это для переименования. Если нет, я проверяю, был ли элемент помечен для переименования, и если да, то я переименовываю его в новый путь события. Но мне действительно не нравится эта идея ...

Редактировать: Хорошо, я что-то реализовал по линии моего «PS»: я заметил, что при переименовании чего-то, идентификаторы двух событий являются последовательными, так что с идентификатором события, содержащего новое имя, я могу получить событие, содержащее старое имя. Я просто использую небольшой словарь в своем интерфейсе для хранения идентификаторов и связанных путей в случае «переименованного» события.

В любом случае, теперь я могу ловить события переименования и даже перемещать события: когда вы перемещаете файл, это «переименованное» событие, которое перехватывается FSEventStream ...

Но у меня осталась еще одна проблема: удаление. Когда я что-то удаляю, он перемещается в корзину: я получаю событие «переименовано». Но проблема в том, что я не получаю второе событие переименования. Только «измененное» событие в файле .DS_Store. Я думаю, что этот файл используется Finder, чтобы узнать, какие файлы находятся в корзине и т. Д. Поэтому я могу проверить изменение этого файла и получить последнее «переименованное» событие, чтобы обнаружить, что файл был отправлен в корзину. Но я использую TotalFinder, который использует Asepsis, который изменяет способ, которым Finder хранит файлы .DS_Store: я больше не получаю «измененный» на этом. Подводя итог: я не могу определить, когда файл отправляется в корзину ...

Есть идеи, как я могу это сделать? Может быть, использовать что-то еще, кроме FSEvents, чтобы поймать только это событие?

Ответы [ 2 ]

13 голосов
/ 05 сентября 2011

Ну, я не нашел идеального ответа на свой вопрос, но я нашел решение, которым я в конечном итоге был действительно доволен, поэтому я подумал, что могу поделитьсяВ корзину. Если вы смотрите только одну папку, вы не поймаете событие, сгенерированное, когда изображение будет помещено в корзину.Итак, я решил сделать следующее: у меня есть класс, который создает поток в корневой папке ("/"), так что он будет перехватывать все события -> это решает проблему отправки файлов в корзину, и всетакие вещи.Затем этот класс позволяет регистрировать делегатов на определенные пути.Поэтому вместо создания нескольких потоков я создаю один большой поток, затем фильтрую события по мере необходимости и создаю много делегатов.

Поэтому все, что мне нужно сделать сейчас, когда я хочу наблюдать за событиями в специальной папке, этоследующее:

[[FSEventsListener instance] addListener:self forPath:somePath];

Мне просто нужно создать экземпляр FSEventListener при запуске приложения и освободить его, когда приложение остановится.И мне просто нужно реализовать следующие 3 метода, которые будут вызываться автоматически:

-(void)fileWasAdded:(NSString *)file;
-(void)fileWasRemoved:(NSString *)file;
-(void)fileWasRenamed:(NSString *)oldFile to:(NSString *)newFile;

Если вам интересен исходный код этой маленькой утилиты, вы можете проверить здесь: http://blog.pcitron.fr/tools/macosx-imageviewer/(утилита была добавлена ​​в версии 0.8)

Я разработал ее как часть небольшого средства просмотра изображений, чтобы синхронизировать пользовательский интерфейс с содержимым диска (он отображает количество изображений, содержащихся в каждой директории и т. д.)Исходный код доступен, и утилита находится в Utils / FSEventsListener.h / .m.

И если по какой-либо случайности кто-то действительно загрузит приложение и взглянет на источники, если вы найдете что-нибудь полезное (улучшение производительности / возможностей, что угодно) не стесняйтесь оставлять комментарии / почту ^^

4 голосов
/ 09 июня 2013

Вы на самом деле поднимаете две проблемы, связанные с FSEvents и переименованием. 1. Файл переименовывается, и старые и новые имена файлов находятся в пределах контролируемых деревьев каталогов. 2. Файл переименован, и одно из имен отсутствует в отслеживаемых деревьях каталогов.

Вы решили (почти) первый вопрос. Также необходимо предоставить вашему приложению возможность узнать, какие события сообщаются в той же группе событий FSEvent. Ваш способ узнать, что два переименования сообщаются последовательно, работает только в том случае, если они находятся в одной и той же группе событий, о которых сообщается в течение одного и того же периода ожидания. Если два события переименования типа 2 происходят одно за другим, но не находятся в одной и той же группе событий, о которых сообщается в одной и той же группе задержек, они фактически не имеют никакого отношения друг к другу - и вы по ошибке будете думать, что один файл был переименован в другой .

Второй тип переименования можно обработать, просто отслеживая каждый каталог в системе с помощью корня, но это приведет к множеству ненужных событий. Вы можете определить, является ли «частичное» переименование результатом перемещения файла из отслеживаемого дерева каталогов или в отслеживаемое дерево каталогов, выполнив stat () для файла. Если stat () завершается с ошибкой с ошибкой 2, то файл был перемещен за пределы отслеживаемого каталога, и его можно рассматривать, как если бы он был удален. Если stat () завершается успешно, событие можно обработать так, как если бы файл был создан.

...