13

I'm trying to use FSEvents to detect when files were added/removed from a specific folder. For the moment, I implemented a simple wrapper around FSEvents, and it works fine : I get all the events.

BUT the problem I have now is that when I rename a file in the Finder, I catch 2 distinct events : the first one of type "renamed" with the old file name, and another one with "renamed" and the new filename. The event ids are different between both calls.

So, how am I supposed to know which "renamed" event contains the old name, and which event contains the old one ?? I tried looking in the documentation, but unfortunately, kFSEventStreamEventFlagItemRenamed is not documented ... it seems new in Lion.

PS: the only way I could think of was : on a renamed event, I check my UI to see if I have an item corresponding to the event path. If so, I flag it for renaming. If not, I check if an item was flagged for renaming, and if so, then I rename it to the new event path. But I really don't like this idea ...

Edit: Ok, I imlemented something along the line of my "PS" : I noticed that when renaming something, the ids of the 2 events are consecutives, so that with the id of the event containing the new name, I can get the event containing the old name. I simply use a little dictionnary in my interface to store ids and associated paths in the case of a "renamed" event.

Anyway, I can now catch rename events, and even move events : when you move a file, it's a "renamed" event which is caught by the FSEventStream ...

But, I still have one last problem : deleting. When I delete something, it's moved to the recycle bin : I receive a "renamed" event. But the problem is that I don't receive the second rename event. Only a "modified" event on the .DS_Store file. I think this file is used by the Finder to know which files are in the bin, etc. So I could check modification to this file, and get the last "renamed" event to detect that a file was sent to the bin. But I'm using TotalFinder which uses Asepsis, which modifies the way the Finder stores .DS_Store files : I no longer receive "modified" on this. To sumarize : I can't detect when a file is sent to the bin ...

Any idea how I can do that ? Maybe use something else than FSEvents to catch only this event ?

4

2 回答 2

13

好吧,我没有找到我的问题的完美答案,但我找到了一个我最终非常满意的解决方案,所以我想我可以分享一下^^

正如我所说,将内容移至垃圾箱时,如果您只观看 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 版本中添加的)

我开发了它作为一个小图像查看器的一部分,以使 UI 与磁盘内容保持同步(它显示每个目录中包含的图像数量等)。源代码可用,实用程序位于 Utils/FSEventsListener.h /.m。

如果有人真的下载了该应用程序并查看源代码,如果您发现任何有用的东西(性能/功能改进等),请随时发表评论/邮件^^

于 2011-09-05T15:54:43.900 回答
4

您实际上提出了与 FSEvents 和重命名相关的两个问题。1. 文件被重命名并且新旧文件名都在被监控的目录树中。2. 一个文件被重命名并且其中一个名称不在被监控的目录树中。

您已经(几乎)解决了第一个问题。还必须为您的应用程序提供一种方法,以了解在同一 FSEvent 事件组中报告了哪些事件。您知道连续报告两个重命名的方法仅在它们位于同一延迟期内报告的同一组事件中时才有效。如果两个类型 2 的重命名事件相继发生,但不在同一延迟组中报告的同一组事件中,则它们实际上彼此无关 - 您会错误地认为一个文件已重命名为另一个文件.

可以通过简单地使用 root 监视系统中的每个目录来处理第二种类型的重命名,但这会给您带来许多不必要的事件。您可以通过对文件执行 stat() 来确定“部分”重命名是由于文件被移出受监视的目录树还是移入受监视的目录树的结果。如果 stat() 失败并显示 errno 为 2,则该文件已被移出被监视的目录,可以将其视为已被删除。如果 stat() 成功,则可以将事件视为文件已创建。

于 2013-06-09T02:11:41.337 回答