NodeJS fs.watch on目录只在被编辑器更改时触发,而不是shell或fs模块

当下面的代码运行时,只有手动编辑和保存tmp.txt才能触发监视,使用我的ide,TextEditor.app或vim。

它不通过写入stream或手动shell输出redirect的方法(键入echo“test”> /path/to/tmp.txt“)。

虽然如果我看文件本身,而不是它的dirname,那么它的作品。

var fs, Path, file, watchPath, w; fs = require('fs' ); Path = require('path'); file = __dirname + '/tmp.txt'; watchPath = Path.dirname(file); // changing this to just file makes it trigger w = fs.watch ( watchPath, function (e,f) { console.log("will not get here by itself"); w.close(); }); fs.writeFileSync(file,"test","utf-8"); fs.createWriteStream(file, { flags:'w', mode: 0777 } ) .end('the_date="'+new Date+'";' ); // another method fails as well setTimeout (function () { fs.writeFileSync(file,"test","utf-8"); },500); // as does this one // child_process exec and spawn fail the same way with or without timeout 

所以问题是:为什么? 以及如何从节点脚本以编程方式触发此事件?

谢谢!

它不会触发,因为对文件内容的更改不是对目录的更改。

在封面上,至less0.6,Mac上的fs.watch使用kqueue,这是一个非常薄的包装kqueue文件系统通知周围。 所以,如果你真的想了解细节,你必须了解kqueue和inode以及类似的东西。

但是,如果你想要一个简短的“谎言对儿童”的解释:用户认为作为一个“文件”是真正的两个单独的东西 – 实际的文件,以及指向实际文件的目录条目。 这就是让你拥有像硬链接一样的东西,以及即使删除它们仍然可以读写的文件,等等。

一般来说,当你写入一个现有的文件时,这不会对目录条目做任何改变,所以任何看着这个目录的人都不会看到任何改变。 这就是为什么echo> tmp.txt不会触发你。

但是,如果你写了一个新的临时文件,然后把它移到旧的文件上,那么它会改变目录项(使它成为新文件的指针,而不是旧文件),所以你会收到通知。 这就是为什么TextEditor.app会触发你。

事情是,你要求看目录而不是文件

文件被修改时目录不会更新,例如通过shellredirect; 在这种情况下,文件被打开,修改并closures。 目录没有改变 – 只有文件是。

当您使用文本编辑器修改文件时,幕后的系统调用通常是这样的:

 fd = open("foo.new") write(fd, new foo contents) unlink("foo") rename("foo.new", "foo") 

这样, foo文件完全是旧文件,或者完全是新文件,并且没有办法使新文件成为“部分文件”。 重命名操作修改目录,从而触发目录监视。

虽然上述答案似乎合理,但并不完全准确。 这实际上是一个非常有用的function,可以听取目录中的文件更改,而不仅仅是“重命名”。 我认为这个特性至less在Windows中是可以正常工作的,而且在0.9.2版本中,它也可以在mac上使用,因为它们改成了支持这个特性的FSEvents API:

版本0.9.2(不稳定)