关于nodejs fs.watch监视文件变化的疑问!
function checkFilesChanges() { let checkFileDirectories = ‘C:/images’; let oldFile=null; fs.watch(checkFileDirectories, (e, filename) => { if(e === ‘rename’) { oldFile=filename; console.log(oldFile,filename) } }) }
为什么我这段代码,我新增了一个文件,能监视到…但是如果我修改了文件 会执行2次,就修改以前的名称,修改之后的名称,都会返回来.怎么才能知道他是从哪个文件修改到哪个文件呢?
比如我从1.txt,修改名称为2.txt 效果写不出来啊!!!
4 回复
有朋友知道吗?
没朋友知道吗?
Note that on most platforms, ‘rename’ is emitted whenever a filename appears or disappears in the directory.
文档上说了的, 当一个文件出现或消失都会触发事件, 重命名就是"消失"->“出现”. 如果某一次触发事件的文件不存在那么它就是"重命名"的原文件, 加个判断即可
function checkFilesChanges() {
let checkFileDirectories = './file';
let oldFile = null;
let rename = true
fs.watch(checkFileDirectories, (e, filename) => {
if (e === 'rename') {
fs.stat(checkFileDirectories + '/' + filename, (err, status) => {
if (err && err.code === 'ENOENT') {
rename = true;
oldFile = filename;
return;
}
if (rename) {
console.log(oldFile, filename);
rename = false;
} else {
console.log(filename);
}
})
}
})
}
这是一个非常复杂的问题。因为rename实际是由两步操作组成的:
remove oldFile
create newFile
下面这段程序是为了说明区分 create/remove/update 这三种情况的:
var fs = require('fs');
fs.watch('.', (eventType, filename) => {
switch(eventType) {
case 'rename':
if (fs.existsSync(filename))
console.log('create', filename, fs.statSync(filename));
else
console.log('remove', filename); // 文件都不存在了,也调用不了fs.statSync了
break;
case 'change':
console.log('update', filename, fs.statSync(filename));
}
});
增加 fs.statSync 是为了说明在 rename 操作发生后,ino项没有发生变化的是rename!!!
{ dev: 16777220,
mode: 33188,
nlink: 1,
uid: 501,
gid: 20,
rdev: 0,
blksize: 4096,
ino: 12932737, // rename行为这项不变化,windows是不是这种情况呢?这需要你自己研究一下了。
size: 399,
blocks: 8,
atime: 2017-05-14T03:41:01.000Z,
mtime: 2017-05-14T03:41:01.000Z,
ctime: 2017-05-14T03:41:01.000Z,
birthtime: 2017-05-14T03:41:01.000Z }
rename = remove + create
因为remove事件发生后,无法调用fs.statSync了,所以进行比对也就变的困难了。
套用楼上方法,认为remove后紧跟create的就是rename,可以用下面代码:
var fs = require('fs');
var oldFile = undefined;
fs.watch('.', (eventType, filename) => {
switch(eventType) {
case 'rename':
if (fs.existsSync(filename)) {
if(oldFile) console.log('rename', oldFile, '->', filename);
else console.log('create', filename);
oldFile = undefined;
}
else {
console.log('remove', filename);
oldFile = filename;
}
break;
case 'change':
console.log('update', filename);
oldFile = undefined;
}
});
应该能适应大部分的情况吧。这样做还有问题遗留,就是事件是remove+rename!当接到remove事件时,谁知道后面是不是还跟着create事件呢?加个 timeout定时?50ms不来create就是remove,来了就是rename? 似乎也能对付过去。谁知道呢?!
测试结果表明,在跨目录rename时,事件出现次序是create+remove,因此这种方法走不通。