fs.watch provides only two possible event types: 'rename'
and 'change'
. Both renaming a file (e.g. using mv
) and deleting it (e.g. using rm
) cause fs.watch
to report a 'rename'
event.
After a file is moved, fs.watch
will continue to report events from it (unless you explicitly close the FSWatcher). When that happens, I'd like to know where the file has moved to.
Is there any way to do this, short of touching every file on the system in turn to see when a 'change'
event is fired?
Node.js makes both file and directory watching easy -- but it's a bit more difficult than you may think. Simply put: Node.js' watching features aren't consistent or performant yet, which the documentation admits.
The simplest way to read a file in Node.js is to use the fs.readFile () method, passing it the file path, encoding and a callback function that will be called with the file data (and the error): Alternatively, you can use the synchronous version fs.readFileSync ():
Watch Files and Directories with Node.js. Watching a file or directory for changes is an important part of automation. We all enjoy using our favorite CSS preprocessor's "watch" feature -- we can still refresh the page and see our changes as though we were simply writing in pure CSS.
Node.js fs.watch () Method Last Updated : 29 Jul, 2020 The fs.watch () method is an inbuilt application programming interface of fs module which is used to continuously watch for changes in the given file or directory. It returns a fs.FSWatcher object that can be used to track the changes in the file.
This looks impossible until node either implements an interface to get file names from a file descriptor (so you could just keep a fd and get the name from there on rename
), or gives back the path/filename reliably along the FSWatcher events.
A workaround to this would be to create a temporary hard link to the target file via fs.link
, then you can get at the file even after changes, though you won't be able to retrieve it's new name.
It's interesting that EventMachine has the same issue: http://eventmachine.rubyforge.org/EventMachine/FileWatch.html#M000291
I guess you would have to look at the original stat of the file and see the inode
which is the identifier of the file. If the file did not move from one partition/filesystem/drive to another (which would actually have to be a copy-then-delete-original operation), then the inode
would be the same.
Unfortunately, there is usually no lookup table of inode
s to get their new name/location. You would have to systematically search the whole system, which might not be so bad assuming you can look at likely places first. or if you can search a limited area only.
You can use a temporary hard link (Ricardo's idea) to detect if it is deleted instead of moved. The number of links counter would change from 1 to 2 when you create your hard link, and would change from 2 back to 1 when the counterpart to your temporary hard link is deleted. If it is deleted, you have no need to look for the file's destination.
If there are only, say a few thousand files in this area, the solution here should work very well, if there are more, depending on your system, it might work, but there might be a delay.
If you wish to decrease the delay, you can have an SQL database of files that you already know the inode
s for. For example, /folder/filea
and /folder/fileb
Both exist with different inode
s. When fileb
is moved to filec
, you have no need to stat
filea
looking for the inode
because you already looked it up previously. This logic should dramatically reduce the number of stat
commands necessary. However, if filea
is deleted and fileb
is moved into filea
s place, this dramatic reduction method would find no results, in which case you would have to fall back to searching the entire working directory.
You do still have the option of ensuring that OS folders like /etc
or /dev
. are only used as a last resort. Which you may never have to search, assuming you can detect deletion using the temporary hard link.
How big is your working area? Do you know for certain whether the file will always be moved from one place to another within a certain working folder? Additional details on your problem environment would be helpful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With