Surveillez un dossier pour les modifications à l'aide de node.js et imprimez les chemins de fichiers lorsqu'ils sont modifiés

87

J'essaie d'écrire un script node.js qui surveille les changements dans un répertoire de fichiers, puis imprime les fichiers qui sont modifiés. Comment puis-je modifier ce script pour qu'il surveille un répertoire (au lieu d'un fichier individuel) et imprime les noms des fichiers dans le répertoire au fur et à mesure qu'ils sont modifiés?

var fs = require('fs'),
    sys = require('sys');
var file = '/home/anderson/Desktop/fractal.png'; //this watches a file, but I want to watch a directory instead
fs.watchFile(file, function(curr, prev) {
    alert("File was modified."); //is there some way to print the names of the files in the directory as they are modified?
});
Vert Anderson
la source
Je me demande si cela est pertinent: stackoverflow.com/questions/12063266/… (je ne suis pas familier avec gruntjs, cependant - j'espère qu'il y a d'autres solutions.)
Anderson Green
Peut-être que quelque chose comme node-inotify-plusplus serait utile: stackoverflow.com/questions/5877263/…
Anderson Green
Quel système d'exploitation utilisez-vous? Cela est important car les mécanismes de bas niveau pour regarder un fichier sont très différents selon les utilisations d'Unix / Linux inotify, OSX FSWatchet je n'ai aucune idée de Windoze mais je suis sûr que Google pourrait vous le dire.
srquinn
1
Bien que j'aie initialement utilisé la plaine node-inotifydans mon projet, je suis finalement passé à node-inotify-plusplusparce que qui n'aime pas les abstractions? =)
srquinn

Réponses:

145

Essayez Chokidar :

var chokidar = require('chokidar');

var watcher = chokidar.watch('file or dir', {ignored: /^\./, persistent: true});

watcher
  .on('add', function(path) {console.log('File', path, 'has been added');})
  .on('change', function(path) {console.log('File', path, 'has been changed');})
  .on('unlink', function(path) {console.log('File', path, 'has been removed');})
  .on('error', function(error) {console.error('Error happened', error);})

Chokidar résout certains des problèmes de multiplateforme en regardant des fichiers en utilisant uniquement fs.

mtsr
la source
3
Gère-t-il les sous-dossiers?
Stepan Yakovenko
1
Un problème avec cela - Lorsque je copie un gros fichier. L'événement d'ajout est déclenché immédiatement, puis j'obtiens des centaines d'événements de modification à mesure que la copie du fichier progresse. Un moyen de déclencher un seul événement lorsque la copie de fichier se termine?
Curious101
5
@ Curious101, avez-vous essayé d'ajouter awaitWriteFinish: true? C'est faux par défaut.
cs_pupil
Je veux demander une chose, est-il utile de l'utiliser sur un système de fichiers volumineux, vous pouvez dire que je veux surveiller /home/terabyte. Eh bien pas récursif
tbhaxor
42

Pourquoi ne pas simplement utiliser l'ancien fs.watch? C'est assez simple.

fs.watch('/path/to/folder', (eventType, filename) => {
console.log(eventType);
// could be either 'rename' or 'change'. new file event and delete
// also generally emit 'rename'
console.log(filename);
})

Pour plus d'informations et de détails sur le paramètre d'options, consultez Node fs Docs

Kaushik Evani
la source
7
Remarque d'avertissement, j'ai testé cela sur mon mac, et ce code ne détecte que ce niveau de dossier et aucun sous-répertoire pour les modifications, alors assurez-vous donc d'ajouter l'option de regarder de manière récursive comme deuxième paramètre; voir les documents liés ci
OzzyTheGiant
1
Note ajoutée à la note de @ OzzyTheGiant: l'option récursive n'est prise en charge que sur macOS et Windows.
Kaushik Evani
Node fs.watch()est un peu maladroit, et vous devez construire votre implémentation anti-rebond gagnée.
mwieczorek
@mwieczorek Que signifie «anti-rebond»?
Thomas Jay Rush
2
@ThomasJayRush un mécanisme qui permet à un certain laps de temps de s'écouler entre l'événement et l'action se déroulant, donc si un événement se déclenche deux fois, l'action n'est appelée qu'une seule fois. C'est un terme d'ingénierie où un bouton physique déclencherait un courant électrique, mais le bouton «rebondirait» une ou plusieurs fois, créant plusieurs pics de courant là où un seul était souhaité - qui peut également être appliqué à la programmation - en particulier JS. medium.com/@jamischarles/what-is-debouncing-2505c0648ff1
mwieczorek
12

essayez chien :

hound = require('hound')

// Create a directory tree watcher.
watcher = hound.watch('/tmp')

// Create a file watcher.
watcher = hound.watch('/tmp/file.txt')

// Add callbacks for file and directory events.  The change event only applies
// to files.
watcher.on('create', function(file, stats) {
  console.log(file + ' was created')
})
watcher.on('change', function(file, stats) {
  console.log(file + ' was changed')
})
watcher.on('delete', function(file) {
  console.log(file + ' was deleted')
})

// Unwatch specific files or directories.
watcher.unwatch('/tmp/another_file')

// Unwatch all watched files and directories.
watcher.clear()

Il s'exécutera une fois le fichier modifié

Sharathi RB
la source