NodeJS fs.watch in the directory is launched only when the editor changes it, but not in the shell or fs module

When the code below is executed, the clock only starts when I edit and save tmp.txt manually, using either my ide, TextEditor.app, or vim.

This is not a method of redirecting a recording stream or manually outputting a shell (entering the echo test "> /path/to/tmp.txt").

Although, if I look at the file itself, and not its name, it works.

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 

So the questions are: why? and how to programmatically fire this event from a node script?

Thanks!

+6
source share
3 answers

It does not start because changing the contents of a file is not a change in the directory.

Under covers of at least 0.6, fs.watch on Mac uses kqueue, and it's a pretty thin wrap around kqueue file system notifications. So, if you really want to understand the details, you must understand kqueue, and inodes and the like.

But if you want a short explanation of “lying to the children”: what the user considers “a file” is actually two separate things — the actual file and the directory entry pointing to the actual file. This allows you to have things like hard links and files that can still be read and written even after they are deleted, etc.

In general, when you write an existing file, it does not make any changes to the entry in the directory, so anyone who looks at this directory does not see any changes. Therefore echo> tmp.txt does not call you.

However, if you, for example, write a new temporary file and then move it over the old file, this will change the entry in the directory (making it a pointer to a new file instead of the old one), so that you will be notified. This is why TextEditor.app launches you.

+9
source

The fact is that you asked to see the directory, not the file.

The directory is not updated when the file changes, for example, by redirecting the shell; in this case, the file opens, changes, and closes. The directory does not change - only the file.

When you use a text editor to modify a file, a typical set of system calls backstage looks something like this:

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

Thus, the foo file is either a completely old file or a completely new file, and there is no way for there to be a “partial file” with the new contents. Renaming operations change the directory, thereby causing a directory scan.

+9
source

Although the answers above seem reasonable, they are not entirely accurate. This is actually a very useful feature that allows you to listen to the directory of file changes, and not just "rename". I think this function works as expected on Windows at least, and in node 0.9.2 it also works for mac, as they have been changed to the FSEvents API, which supports this function:

Version 0.9.2 (unstable)

+4
source

Source: https://habr.com/ru/post/916711/


All Articles