使用Lion上的FSEvents跟踪文件重命名/删除

Cit*_*ron 13 objective-c fsevents osx-lion

我正在尝试使用FSEvents来检测何时从特定文件夹添加/删除文件.目前,我在FSEvents周围实现了一个简单的包装器,它工作正常:我得到了所有的事件.

但我现在遇到的问题是,当我在Finder中重命名文件时,我捕获了2个不同的事件:第一个类型是"重命名"旧文件名,另一个是"重命名"和新文件名.两个调用之间的事件ID都不同.

那么,我怎么知道哪个"重命名"事件包含旧名称,哪个事件包含旧名称?我试着查看文档,但不幸的是,kFSEventStreamEventFlagItemRenamed没有记录......它在Lion中似乎是新的.

PS:我能想到的唯一方法是:在重命名的事件上,我检查我的UI,看看我是否有一个与事件路径对应的项目.如果是这样,我将其标记为重命名.如果没有,我检查项目是否被标记为重命名,如果是,则将其重命名为新的事件路径.但我真的不喜欢这个想法......

编辑:好的,我在我的"PS"行中发现了一些内容:我注意到在重命名时,2个事件的id是连续的,所以使用包含新名称的事件的id,我可以得到事件包含旧名称.在"重命名"事件的情况下,我只是在界面中使用一个小字典来存储id和相关路径.

无论如何,我现在可以捕获重命名事件,甚至移动事件:当你移动文件时,它是一个"重命名"的事件,它被FSEventStream捕获...

但是,我还有最后一个问题:删除.当我删除某些内容时,它会被移动到回收站:我收到一个"重命名"的事件.但问题是我没有收到第二次重命名事件.仅.DS_Store文件上的"已修改"事件.我认为Finder使用此文件来了解bin中的文件等等.因此,我可以检查对此文件的修改,并获取最后一次"重命名"事件以检测文件是否已发送到bin.但是我使用的是使用Asepsis的TotalFinder,它修改了Finder存储的方式.DS_Store文件:我不再收到"修改"了.要sumarize:我无法检测何时将文件发送到bin ...

知道我怎么能这样做吗?也许使用除FSEvents以外的其他东西来捕捉这个事件?

Cit*_*ron 13

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

正如我所说,当把东西搬到垃圾桶时,如果你只是看一个文件夹,你就不会看到将图像放入垃圾箱时产生的事件.所以,我决定执行以下操作:我有一个类在根文件夹("/")上创建一个流,以便它将捕获所有事件 - >这解决了文件被发送到垃圾箱的问题,以及所有这样的东西.然后,这个类允许在某些路径上注册代理.因此,我不是创建很多流,而是创建一个大流,然后根据需要过滤事件,并创建许多委托.

因此,当我想在特殊文件夹上观看事件时,我现在要做的就是:

[[FSEventsListener instance] addListener:self forPath:somePath];
Run Code Online (Sandbox Code Playgroud)

我只需要在应用程序启动时创建一个FSEventListener实例,并在应用程序停止时释放它.我只需要实现以下3种自动调用的方法:

-(void)fileWasAdded:(NSString *)file;
-(void)fileWasRemoved:(NSString *)file;
-(void)fileWasRenamed:(NSString *)oldFile to:(NSString *)newFile;
Run Code Online (Sandbox Code Playgroud)

如果您对这个小实用程序的源代码感兴趣,可以在这里查看:http://blog.pcitron.fr/tools/macosx-imageviewer/(该实用程序是在0.8版本中添加的)

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

如果有人实际下载应用程序并查看源代码,如果您发现任何有用的内容(性能/功能改进,无论如何),请随时删除评论/邮件^^


小智 5

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

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

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