read nodejs node filesystem example javascript node.js filesystems

javascript - filesystem - readfile nodejs



Caminando un directorio con Node.js (6)

Tengo un problema con este código en node.js. Quiero recorrer recursivamente un árbol de directorios y aplicar la action devolución de llamada a cada archivo en el árbol. Este es mi código en este momento:

var fs = require("fs"); // General function var dive = function (dir, action) { // Assert that it''s a function if (typeof action !== "function") action = function (error, file) { }; // Read the directory fs.readdir(dir, function (err, list) { // Return the error if something went wrong if (err) return action(err); // For every file in the list list.forEach(function (file) { // Full path of that file path = dir + "/" + file; // Get the file''s stats fs.stat(path, function (err, stat) { console.log(stat); // If the file is a directory if (stat && stat.isDirectory()) // Dive into the directory dive(path, action); else // Call the action action(null, path); }); }); }); };

El problema es que en la estadística de cada bucle se llama para cada archivo a través de la path variable. Cuando se llama a la devolución de llamada, la path ya tiene otro valor, por lo que se dive en los directorios incorrectos o llama a la action de los archivos incorrectos.

Probablemente este problema podría resolverse fácilmente usando fs.statSync , pero esta no es la solución que preferiría, ya que está bloqueando el proceso.


No estoy seguro de si realmente debería publicar esto como una respuesta, pero para su conveniencia y para otros usuarios, aquí hay una versión reescrita de OP que puede ser útil. Proporciona:

  • Mejor soporte a la gestión de errores.
  • Una devolución de llamada de finalización global que se llama cuando se completa la exploración

El código:

/** * dir: path to the directory to explore * action(file, stat): called on each file or until an error occurs. file: path to the file. stat: stat of the file (retrived by fs.stat) * done(err): called one time when the process is complete. err is undifined is everything was ok. the error that stopped the process otherwise */ var walk = function(dir, action, done) { // this flag will indicate if an error occured (in this case we don''t want to go on walking the tree) var dead = false; // this flag will store the number of pending async operations var pending = 0; var fail = function(err) { if(!dead) { dead = true; done(err); } }; var checkSuccess = function() { if(!dead && pending == 0) { done(); } }; var performAction = function(file, stat) { if(!dead) { try { action(file, stat); } catch(error) { fail(error); } } }; // this function will recursively explore one directory in the context defined by the variables above var dive = function(dir) { pending++; // async operation starting after this line fs.readdir(dir, function(err, list) { if(!dead) { // if we are already dead, we don''t do anything if (err) { fail(err); // if an error occured, let''s fail } else { // iterate over the files list.forEach(function(file) { if(!dead) { // if we are already dead, we don''t do anything var path = dir + "/" + file; pending++; // async operation starting after this line fs.stat(path, function(err, stat) { if(!dead) { // if we are already dead, we don''t do anything if (err) { fail(err); // if an error occured, let''s fail } else { if (stat && stat.isDirectory()) { dive(path); // it''s a directory, let''s explore recursively } else { performAction(path, stat); // it''s not a directory, just perform the action } pending--; checkSuccess(); // async operation complete } } }); } }); pending--; checkSuccess(); // async operation complete } } }); }; // start exploration dive(dir); };



Otra biblioteca adecuada es filehound . Es compatible con el filtrado de archivos (si es necesario), devoluciones de llamada y promesas.

Por ejemplo:

const Filehound = require(''filehound''); function action(file) { console.log(`process ${file}`) } Filehound.create() .find((err, files) => { if (err) { return console.error(`error: ${err}`); } files.forEach(action); });

La biblioteca está bien documentada y proporciona numerosos ejemplos de casos de uso comunes. https://github.com/nspragg/filehound

Descargo de responsabilidad: Soy el autor.


Use node-dir para esto. Como necesita una acción separada para directorios y archivos, le daré 2 iteradores simples usando node-dir.

Recorrer de forma asíncrona los archivos de un directorio y sus subdirectorios y pasar una matriz de rutas de archivos a una devolución de llamada.

var dir = require(''node-dir''); dir.files(__dirname, function(err, files) { if (err) throw err; console.log(files); //we have an array of files now, so now we''ll iterate that array files.forEach(function(filepath) { actionOnFile(null, filepath); }) });

Recorrer asíncronamente los subdirectorios de un directorio y sus subdirectorios y pasar una matriz de rutas de directorio a una devolución de llamada.

var dir = require(''node-dir''); dir.subdirs(__dirname, function(err, subdirs) { if (err) throw err; console.log(subdirs); //we have an array of subdirs now, so now we''ll iterate that array subdirs.forEach(function(filepath) { actionOnDir(null, filepath); }) });


var path = dir + "/" + file;

Olvidaste hacer del path una variable local. Ahora no se cambiará detrás de su espalda en el bucle.


function loop( ) { var item = list.shift( ); if ( item ) { // content of the loop functionWithCallback( loop ); } else { // after the loop has ended whatever( ); } }