Básicamente hay dos formas de lograr esto. En un entorno asíncrono, notará que hay dos tipos de bucles: serie y paralelo. Un bucle en serie espera a que se complete una iteración antes de pasar a la siguiente iteración; esto garantiza que cada iteración del bucle se complete en orden. En un bucle paralelo, todas las iteraciones se inician al mismo tiempo, y una puede completarse antes que otra, sin embargo, es mucho más rápido que un bucle en serie. Entonces, en este caso, probablemente sea mejor usar un bucle paralelo porque no importa en qué orden se complete la caminata, siempre que se complete y devuelva los resultados (a menos que los desee en orden).
Un bucle paralelo se vería así:
var fs = require('fs');
var path = require('path');
var walk = function(dir, done) {
var results = [];
fs.readdir(dir, function(err, list) {
if (err) return done(err);
var pending = list.length;
if (!pending) return done(null, results);
list.forEach(function(file) {
file = path.resolve(dir, file);
fs.stat(file, function(err, stat) {
if (stat && stat.isDirectory()) {
walk(file, function(err, res) {
results = results.concat(res);
if (!--pending) done(null, results);
});
} else {
results.push(file);
if (!--pending) done(null, results);
}
});
});
});
};
Un bucle en serie se vería así:
var fs = require('fs');
var path = require('path');
var walk = function(dir, done) {
var results = [];
fs.readdir(dir, function(err, list) {
if (err) return done(err);
var i = 0;
(function next() {
var file = list[i++];
if (!file) return done(null, results);
file = path.resolve(dir, file);
fs.stat(file, function(err, stat) {
if (stat && stat.isDirectory()) {
walk(file, function(err, res) {
results = results.concat(res);
next();
});
} else {
results.push(file);
next();
}
});
})();
});
};
Y para probarlo en su directorio de inicio (ADVERTENCIA: la lista de resultados será enorme si tiene muchas cosas en su directorio de inicio):
walk(process.env.HOME, function(err, results) {
if (err) throw err;
console.log(results);
});
EDITAR: ejemplos mejorados.
file = dir + '/' + file;
Esto no es recomendable. Deberías usar:var path = require('path'); file = path.resolve(dir, file);
path.resolve(...)
usas obtendrás una ruta adecuada ya sea que estés en Windows o Unix :) Lo que significa que obtendrás algo así comoC:\\some\\foo\\path
en Windows y/some/foo/path
en sistemas Unixrequire('node-dir').files(__dirname, function(err, files) { console.log(files); });
!--
sintaxis, se ha formulado una pregunta al respectoEste utiliza la cantidad máxima de características nuevas y de moda disponibles en el nodo 8, incluidas Promesas, util / promisify, destructuring, async-wait, map + reduce y más, haciendo que sus compañeros de trabajo se rasquen la cabeza mientras intentan averiguar qué está pasando.
Nodo 8+
Sin dependencias externas.
Uso
Nodo 10.10+
Actualizado para el nodo 10+ con aún más whizbang:
Tenga en cuenta que a partir del nodo 11.15.0 puede usarlo en
files.flat()
lugar deArray.prototype.concat(...files)
aplanar la matriz de archivos.Nodo 11+
Si quieres volar la cabeza de todos por completo, puedes usar la siguiente versión usando iteradores asíncronos . Además de ser realmente genial, también permite a los consumidores obtener resultados uno por uno, lo que lo hace más adecuado para directorios realmente grandes.
El uso ha cambiado porque el tipo de retorno ahora es un iterador asíncrono en lugar de una promesa
En caso de que alguien esté interesado, he escrito más sobre iteradores asíncronos aquí: https://qwtel.com/posts/software/async-generators-in-the-wild/
fuente
subdir
ysubdirs
es engañosa, ya que pueden ser realmente archivos (sugiero algo comoitemInDir
oitem_in_dir
simplemente en suitem
lugar), pero esta solución se siente más limpia que la aceptada y es mucho menos código. Tampoco lo encuentro mucho más complicado que el código en la respuesta aceptada. +1require(fs).promises
y simplemente soltando porutil.promisify
completo. Personalmente alias fs a fs.promises.readdir
AKA como el objeto de opciones para quereaddir(dir, {withFileTypes: true})
esto devuelva todos los elementos con su información de tipo, así que no necesitaremos llamarstat
para obtener la información quereaddir
ahora nos da espalda. Esto nos ahorra la necesidad de hacer llamadas sys adicionales. Detalles aquíwithFileTypes
. Gracias por el consejo.return Array.prototype.concat(...files);
conlet result = Array.prototype.concat(...files); return result.map(file => file.split('\\').join('/'));
puede asegurarse de que los directorios devuelvan un "/" y no un "\". Si no te importa la expresión regular, también puedes hacerloreturn result.map(file => file.replace(/\\/g, '/'));
En caso de que alguien lo encuentre útil, también armé una versión sincrónica .
Consejo: Para usar menos recursos al filtrar. Filtrar dentro de esta función misma. Por ejemplo, reemplazar
results.push(file);
con el siguiente código. Ajuste según sea necesario:fuente
lstat
en su lugar? O bien, agregue una verificación de recursividad para limitar el nivel de recursividad.A. Eche un vistazo al módulo de archivo . Tiene una función llamada caminar:
¡Esto puede ser para ti! Y sí, es asíncrono. Sin embargo, creo que tendría que agregar el camino completo usted mismo, si los necesitara.
B. Una alternativa, e incluso una de mis favoritas: use el Unix
find
para eso. ¿Por qué hacer algo de nuevo, que ya ha sido programado? Tal vez no sea exactamente lo que necesita, pero vale la pena echarle un vistazo:Find tiene un buen mecanismo de almacenamiento en caché integrado que hace que las búsquedas posteriores sean muy rápidas, siempre que solo hayan cambiado algunas carpetas.
fuente
Otro buen paquete de npm es glob .
npm install glob
Es muy poderoso y debe cubrir todas sus necesidades recurrentes.
Editar:
En realidad no estaba perfectamente contento con Glob, así que creé readdirp .
Estoy muy seguro de que su API hace que encontrar archivos y directorios de forma recursiva y aplicar filtros específicos sea muy fácil.
Lea su documentación para tener una mejor idea de lo que hace e instalar a través de:
npm install readdirp
fuente
Recomiendo usar node-glob para lograr esa tarea.
fuente
Si desea usar un paquete npm, la llave inglesa es bastante buena.
EDITAR (2018):
cualquiera que haya leído en los últimos tiempos: el autor dejó de usar este paquete en 2015:
fuente
denodify
esto? La devolución de llamada se dispara varias veces (recursivamente). Entonces, usarQ.denodify(wrench.readdirRecursive)
solo devuelve el primer resultado.Me encantó la respuesta de chjj anterior y no habría podido crear mi versión del bucle paralelo sin ese comienzo.
También creé un Gist . Comentarios bienvenidos Todavía estoy comenzando en el reino NodeJS, así que esa es una forma en que espero aprender más.
fuente
Con recursividad
Vocación
fuente
/
pero utilizando elpath
módulo:path.join(searchPath, file)
. De esa manera, obtendrá las rutas correctas independientemente del sistema operativo.Use node-dir para producir exactamente la salida que desea
fuente
He codificado esto recientemente, y pensé que tendría sentido compartir esto aquí. El código hace uso de la biblioteca asíncrona .
Puedes usarlo así:
fuente
Una biblioteca llamada Filehound es otra opción. Buscará recursivamente un directorio dado (directorio de trabajo por defecto). Es compatible con varios filtros, devoluciones de llamada, promesas y búsquedas de sincronización.
Por ejemplo, busque en el directorio de trabajo actual todos los archivos (utilizando devoluciones de llamada):
O promete y especifica un directorio específico:
Consulte los documentos para obtener más casos de uso y ejemplos de uso: https://github.com/nspragg/filehound
Descargo de responsabilidad: soy el autor.
fuente
Usando async / await, esto debería funcionar:
Puedes usar bluebird.Promisify o esto:
Vea mi otra respuesta para un enfoque generador que puede dar resultados aún más rápido.
fuente
Asíncrono
Sincronización
Asíncrono legible
Nota: ambas versiones seguirán enlaces simbólicos (igual que el original
fs.readdir
)fuente
Echa un vistazo a la biblioteca final-fs . Proporciona una
readdirRecursive
función:fuente
Implementación de promesa independiente
Estoy usando la biblioteca de promesas when.js en este ejemplo.
He incluido un parámetro opcional
includeDir
que incluirá directorios en la lista de archivos si está configurado entrue
.fuente
Vale la pena considerar klaw y klaw-sync para este tipo de cosas. Estos eran parte de node-fs-extra .
fuente
Aquí hay otra implementación más. Ninguna de las soluciones anteriores tiene limitadores, por lo que si la estructura de su directorio es grande, todos se agotarán y eventualmente se quedarán sin recursos.
Usar una concurrencia de 50 funciona bastante bien y es casi tan rápido como implementaciones más simples para estructuras de directorios pequeñas.
fuente
El módulo recursive-readdir tiene esta funcionalidad.
fuente
Modifiqué la respuesta basada en Promesa de Trevor Senior para trabajar con Bluebird
fuente
Por diversión, aquí hay una versión basada en flujo que funciona con la biblioteca de secuencias highland.js. Fue escrito por Victor Vu.
fuente
Usando Promesas ( Q ) para resolver esto en un estilo funcional:
Devuelve la promesa de una matriz, por lo que puede usarla como:
fuente
Debo agregar a la lista la biblioteca de lijadoras basada en Promise .
fuente
Usando bluebird promise.coroutine:
fuente
Como todos deberían escribir el suyo, hice uno.
walk (dir, cb, endCb) cb (archivo) endCb (err | null)
SUCIO
fuente
echa un vistazo a loaddir https://npmjs.org/package/loaddir
npm install loaddir
Puede usar en
fileName
lugar debaseName
si necesita la extensión también.Una ventaja adicional es que también mirará los archivos y volverá a llamar a la devolución de llamada. Hay toneladas de opciones de configuración para hacerlo extremadamente flexible.
Acabo de rehacer la
guard
gema de ruby usando loaddir en poco tiempofuente
Esta es mi respuesta. Espero que pueda ayudar a alguien.
Mi objetivo es hacer que la rutina de búsqueda pueda detenerse en cualquier lugar, y para un archivo encontrado, indica la profundidad relativa a la ruta original.
fuente
Aquí hay un método recursivo para obtener todos los archivos, incluidos los subdirectorios.
fuente
Otra simple y útil.
fuente
Así es como uso la función nodejs fs.readdir para buscar recursivamente un directorio.
Digamos que tiene una ruta llamada '/ base de datos' en la raíz de proyectos de su nodo. Una vez que se resuelva esta promesa, debería escupir una matriz de cada archivo en '/ database'.
fuente