Подтвердить что ты не робот

Переименование файла/удаление с помощью FSEvents на Lion

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

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

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

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

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

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

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

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

4b9b3361

Ответ 1

Ну, я не нашел идеального ответа на мой вопрос, но я нашел решение, которое в конечном итоге было действительно удовлетворено, поэтому я подумал, что могу поделиться ^^

Как я уже сказал, при перемещении материала в корзину, если вы просматриваете только одну папку, вы не поймаете событие, сгенерированное, когда изображение помещено в корзину. Итак, я решил сделать следующее: У меня есть класс, который создает поток в корневой папке ( "/" ), чтобы он поймал все события → это решает проблему отправки файлов в корзину и все такое. Затем этот класс позволяет зарегистрировать делегатов по определенным адресам. Таким образом, вместо создания множества потоков я создаю один большой поток, а затем фильтрует события по мере необходимости, и я создаю много делегатов.

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

[[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/.м.

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

Ответ 2

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

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

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