这是一个非常复杂的问题。因为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,因此这种方法走不通。