fs.watch仅提供两种可能的事件类型:'rename'
和'change'
。重命名文件(例如使用mv
)并将其删除(例如使用rm
)都会导致fs.watch
报告'rename'
事件。
移动文件后,fs.watch
将继续报告其中的事件(除非您明确关闭FSWatcher)。当发生这种情况时,我想知道文件的移动位置。
有没有办法做到这一点,而不是依次触摸系统上的每个文件来查看'change'
事件何时被触发?
答案 0 :(得分:3)
在节点实现从文件描述符中获取文件名的接口之前看起来是不可能的(因此你可以保留fd并从rename
获取名称),或者可靠地返回路径/文件名沿着FSWatcher活动。
解决此问题的方法是通过fs.link
创建指向目标文件的临时硬链接,然后即使在更改后也可以访问该文件,但您无法检索它的新名称。
有趣的是EventMachine有同样的问题:http://eventmachine.rubyforge.org/EventMachine/FileWatch.html#M000291
答案 1 :(得分:1)
我想您必须查看文件的原始统计信息,并查看inode
这是文件的标识符。如果文件没有从一个分区/文件系统/驱动器移动到另一个(实际上必须是copy-then-delete-original操作),那么inode
将是相同的。
不幸的是,通常没有inode
s的查找表来获取他们的新名称/位置。您必须系统地搜索整个系统,假设您可以先查看可能的位置,这可能不会那么糟糕。或者如果你只能搜索有限的区域。
您可以使用临时硬链接(里卡多的想法)来检测它是否被删除而不是移动。创建硬链接时,链接计数器的数量将从1更改为2,当删除临时硬链接的对应项时,链接计数器将从2更改为1。如果删除它,则无需查找文件的目的地。
如果只有,在这个区域说几千个文件,这里的解决方案应该可以很好地工作,如果有更多,取决于你的系统,它可能会工作,但可能会有延迟。
如果您希望减少延迟,可以拥有一个SQL数据库,其中包含您已知道inode
的文件。例如,/folder/filea
和/folder/fileb
两者都存在不同的inode
s。将fileb
移至filec
后,您无需stat
filea
查找inode
,因为您之前已查找过stat
。这个逻辑应该大大减少必要的filea
命令的数量。但是,如果删除了fileb
并将filea
移到了/etc
的位置,那么这种戏剧性的缩减方法就会找不到结果,在这种情况下,您将不得不回头搜索整个工作。目录
您仍然可以选择确保操作系统文件夹,例如/dev
或{{1}}。仅用作最后的手段。假设您可以使用临时硬链接检测删除,那么您可能永远不必搜索。
您的工作区域有多大?您是否确定该文件是否始终在某个工作文件夹中从一个地方移动到另一个地方?有关您的问题环境的其他详细信息将会有所帮助。