Как в NodeJS реализовать автоматическое отслеживание изменение содержимого в каталоге (папке)?

Коллеги, у меня есть такая функция,

const getFiles = (dir, files_) => {
  files_ = files_ || [];
  let files = fs.readdirSync(dir);
  for (var i in files) {
    var name = dir + '/' + files[i];
    if (fs.statSync(name).isDirectory()) {
      getFiles(name, files_);
    } else {
      files_.push(name);
    }
  }
  return files_;
};

console.log(getFiles('./frontend/multimedia/image'));

которая прекрасно работает, но как мне данной функции указать, чтобы она отслеживала за изменениями содержимым в папке (удаление или добавление файлов)?

Единственно, что пришло в голову это запускать getFiles('./frontend/multimedia/image') в setInterval().

Понимаю, что это - не самый лучший способ...

Так как же мне не перезапускать эту функцию, а реализовать в ней отслеживание за папкой?


Ответы (1 шт):

Автор решения: nörbörnën

В nodejs есть стандартные средства для отслеживания изменений файла или каталога.

fs.watch(filename[, options][, listener])

const fs = require('fs');

const w = fs.watch(
  process.cwd(),
  { recursive: true },
  (eventType, filename) => {
    console.log('listener', eventType, filename);
  }
);

w.on('change', (eventType, filename) => {
  console.log('[h] change', eventType, filename);
});
w.on('error', (err) => console.error('[h] error', err));
w.on('close', () => console.log('[h] close'));

Вывод в консоль:

$ node src/fs-watch-1/index.js 
rename tmp
rename tmp/q
rename tmp/.#q2
rename tmp/q2
rename tmp/.#q2
rename tmp/q
rename tmp
rename tmp1

Ими можно пользоваться, однако callback-и получают только два типа событий eventType - 'rename' либо 'change'. И не на всех типах операционных систем получают имя модифицированного файла.

В общем, для решения задачи "отслеживать удаление или добавление файлов", селективность инструмента низкая и прийдётся руками дописывать проверки.


Рекомендую использовать пакет chokidar. С ним задача решается легко:

const chokidar = require('chokidar');

const watcher = chokidar.watch(process.cwd(), {
  persistent: true
});
watcher.on('ready', () => {
  watcher.on('add', (path) => console.log(`File ${path} has been added`))
    .on('unlink', (path) => console.log(`File ${path} has been removed`))
    .on('addDir', (path) => console.log(`Directory ${path} has been added`))
    .on('unlinkDir', (path) => console.log(`Directory ${path} has been removed`));
});

Вывод в консоль:

$ node src/fs-watch-1/chokidar.js 
File /Users/xxx/git/stackoverflow-practice/tmp/q3 has been removed
File /Users/xxx/git/stackoverflow-practice/tmp/q1 has been removed
File /Users/xxx/git/stackoverflow-practice/tmp/q2 has been removed
Directory /Users/xxx/git/stackoverflow-practice/tmp has been removed

Directory /Users/xxx/git/stackoverflow-practice/tmp has been added
File /Users/xxx/git/stackoverflow-practice/tmp/q has been added
→ Ссылка