Me gustaría encontrar todos los archivos * .html en la carpeta src y todas sus subcarpetas usando nodejs. ¿Cuál es la mejor manera de hacerlo?
var folder = '/project1/src';
var extension = 'html';
var cb = function(err, results) {
// results is an array of the files with path relative to the folder
console.log(results);
}
// This function is what I am looking for. It has to recursively traverse all sub folders.
findFiles(folder, extension, cb);
Creo que muchos desarrolladores deberían tener una solución excelente y probada y es mejor usarla que escribir una yo mismo.
node.js
find
file-extension
Nicolas S.Xu
fuente
fuente
Respuestas:
node.js, función simple recursiva:
var path = require('path'), fs=require('fs'); function fromDir(startPath,filter){ //console.log('Starting from dir '+startPath+'/'); if (!fs.existsSync(startPath)){ console.log("no dir ",startPath); return; } var files=fs.readdirSync(startPath); for(var i=0;i<files.length;i++){ var filename=path.join(startPath,files[i]); var stat = fs.lstatSync(filename); if (stat.isDirectory()){ fromDir(filename,filter); //recurse } else if (filename.indexOf(filter)>=0) { console.log('-- found: ',filename); }; }; }; fromDir('../LiteScript','.html');
agregue RegExp si desea ser elegante y una devolución de llamada para hacerlo genérico.
var path = require('path'), fs=require('fs'); function fromDir(startPath,filter,callback){ //console.log('Starting from dir '+startPath+'/'); if (!fs.existsSync(startPath)){ console.log("no dir ",startPath); return; } var files=fs.readdirSync(startPath); for(var i=0;i<files.length;i++){ var filename=path.join(startPath,files[i]); var stat = fs.lstatSync(filename); if (stat.isDirectory()){ fromDir(filename,filter,callback); //recurse } else if (filter.test(filename)) callback(filename); }; }; fromDir('../LiteScript',/\.html$/,function(filename){ console.log('-- found: ',filename); });
fuente
me gusta usar el paquete glob :
const glob = require('glob'); glob(__dirname + '/**/*.html', {}, (err, files)=>{ console.log(files) })
fuente
¡¿Qué, espera ?! ... Está bien, tal vez esto también tenga más sentido para alguien más.
[ nodejs 7 fíjate]
fs = import('fs'); let dirCont = fs.readdirSync( dir ); let files = dirCont.filter( function( elm ) {return elm.match(/.*\.(htm?html)/ig);});
Haga lo que sea con regex, conviértalo en un argumento que establezca en la función con un valor predeterminado, etc.
fuente
wl
tiene mucho sentido. Además, falta la importación de fs. Las tres líneas que necesita son: 1.const fs = require('fs');
2.const dirCont = fs.readdirSync( dir );
3.const files = dirCont.filter( ( elm ) => /.*\.(htm?html)/gi.test(elm) );
Basado en el código de Lucio, hice un módulo. Regresará con todos los archivos con extensiones específicas debajo de uno. Solo publícalo aquí en caso de que alguien lo necesite.
var path = require('path'), fs = require('fs'); /** * Find all files recursively in specific folder with specific extension, e.g: * findFilesInDir('./project/src', '.html') ==> ['./project/src/a.html','./project/src/build/index.html'] * @param {String} startPath Path relative to this file or other file which requires this files * @param {String} filter Extension name, e.g: '.html' * @return {Array} Result files with path string in an array */ function findFilesInDir(startPath,filter){ var results = []; if (!fs.existsSync(startPath)){ console.log("no dir ",startPath); return; } var files=fs.readdirSync(startPath); for(var i=0;i<files.length;i++){ var filename=path.join(startPath,files[i]); var stat = fs.lstatSync(filename); if (stat.isDirectory()){ results = results.concat(findFilesInDir(filename,filter)); //recurse } else if (filename.indexOf(filter)>=0) { console.log('-- found: ',filename); results.push(filename); } } return results; } module.exports = findFilesInDir;
fuente
Puede utilizar Filehound para hacer esto.
Por ejemplo: busque todos los archivos .html en / tmp:
const Filehound = require('filehound'); Filehound.create() .ext('html') .paths("/tmp") .find((err, htmlFiles) => { if (err) return console.error("handle err", err); console.log(htmlFiles); });
Para obtener más información (y ejemplos), consulte los documentos: https://github.com/nspragg/filehound
Descargo de responsabilidad : soy el autor.
fuente
He mirado las respuestas anteriores y he mezclado esta versión que funciona para mí:
function getFilesFromPath(path, extension) { let files = fs.readdirSync( path ); return files.filter( file => file.match(new RegExp(`.*\.(${extension})`, 'ig'))); } console.log(getFilesFromPath("./testdata", ".txt"));
Esta prueba devolverá una matriz de nombres de archivos de los archivos que se encuentran en la carpeta en la ruta
./testdata
. Trabajando en la versión de nodo 8.11.3.fuente
.*\.(${extension})$
Puede utilizar la ayuda del sistema operativo para esto. Aquí hay una solución multiplataforma:
1. La función de abajo usa
ls
ydir
no busca de forma recursiva, pero tiene rutas relativasvar exec = require('child_process').exec; function findFiles(folder,extension,cb){ var command = ""; if(/^win/.test(process.platform)){ command = "dir /B "+folder+"\\*."+extension; }else{ command = "ls -1 "+folder+"/*."+extension; } exec(command,function(err,stdout,stderr){ if(err) return cb(err,null); //get rid of \r from windows stdout = stdout.replace(/\r/g,""); var files = stdout.split("\n"); //remove last entry because it is empty files.splice(-1,1); cb(err,files); }); } findFiles("folderName","html",function(err,files){ console.log("files:",files); })
2. La función de abajo usa
find
ydir
, busca de forma recursiva, pero en Windows tiene rutas absolutas.var exec = require('child_process').exec; function findFiles(folder,extension,cb){ var command = ""; if(/^win/.test(process.platform)){ command = "dir /B /s "+folder+"\\*."+extension; }else{ command = 'find '+folder+' -name "*.'+extension+'"' } exec(command,function(err,stdout,stderr){ if(err) return cb(err,null); //get rid of \r from windows stdout = stdout.replace(/\r/g,""); var files = stdout.split("\n"); //remove last entry because it is empty files.splice(-1,1); cb(err,files); }); } findFiles("folder","html",function(err,files){ console.log("files:",files); })
fuente
El siguiente código hace una búsqueda recursiva dentro de ./ (cámbielo apropiadamente) y devuelve una matriz de nombres de archivos absolutos que terminan en .html
var fs = require('fs'); var path = require('path'); var searchRecursive = function(dir, pattern) { // This is where we store pattern matches of all files inside the directory var results = []; // Read contents of directory fs.readdirSync(dir).forEach(function (dirInner) { // Obtain absolute path dirInner = path.resolve(dir, dirInner); // Get stats to determine if path is a directory or a file var stat = fs.statSync(dirInner); // If path is a directory, scan it and combine results if (stat.isDirectory()) { results = results.concat(searchRecursive(dirInner, pattern)); } // If path is a file and ends with pattern then push it onto results if (stat.isFile() && dirInner.endsWith(pattern)) { results.push(dirInner); } }); return results; }; var files = searchRecursive('./', '.html'); // replace dir and pattern // as you seem fit console.log(files);
fuente
No puedo agregar un comentario debido a la reputación, pero tenga en cuenta lo siguiente:
Usar fs.readdir o node-glob para encontrar un conjunto de archivos comodín en una carpeta de 500,000 archivos tomó ~ 2 s. El uso de exec con DIR tomó ~ 0.05s (no recursivo) o ~ 0.45s (recursivo). (Estaba buscando ~ 14 archivos que coincidan con mi patrón en un solo directorio).
Hasta ahora, no he podido encontrar ninguna implementación de nodejs que utilice comodines de SO de bajo nivel en busca de eficiencia. Pero el código anterior basado en DIR / ls funciona maravillosamente en Windows en términos de eficiencia. Linux find, sin embargo, probablemente será muy lento para directorios grandes.
fuente
mis dos centavos, usando map en lugar de for-loop
var path = require('path'), fs = require('fs'); var findFiles = function(folder, pattern = /.*/, callback) { var flist = []; fs.readdirSync(folder).map(function(e){ var fname = path.join(folder, e); var fstat = fs.lstatSync(fname); if (fstat.isDirectory()) { // don't want to produce a new array with concat Array.prototype.push.apply(flist, findFiles(fname, pattern, callback)); } else { if (pattern.test(fname)) { flist.push(fname); if (callback) { callback(fname); } } } }); return flist; }; // HTML files var html_files = findFiles(myPath, /\.html$/, function(o) { console.log('look what we have found : ' + o} ); // All files var all_files = findFiles(myPath);
fuente
Eche un vistazo a file-regex
let findFiles = require('file-regex') let pattern = '\.js' findFiles(__dirname, pattern, (err, files) => { console.log(files); })
Este fragmento de código anterior imprimiría todos los
js
archivos en el directorio actual.fuente
Acabo de notar, que está utilizando métodos de sincronización fs, que podría bloquear la aplicación, aquí hay una manera asíncrona basada en el uso de la promesa asíncrono y q , se puede ejecutar con start = / = myfolder myfile.js FILTRO "jpg" nodo, suponiendo que pones el siguiente código en un archivo llamado myfile.js:
Q = require("q") async = require("async") path = require("path") fs = require("fs") function findFiles(startPath, filter, files){ var deferred; deferred = Q.defer(); //main deferred //read directory Q.nfcall(fs.readdir, startPath).then(function(list) { var ideferred = Q.defer(); //inner deferred for resolve of async each //async crawling through dir async.each(list, function(item, done) { //stat current item in dirlist return Q.nfcall(fs.stat, path.join(startPath, item)) .then(function(stat) { //check if item is a directory if (stat.isDirectory()) { //recursive!! find files in subdirectory return findFiles(path.join(startPath, item), filter, files) .catch(function(error){ console.log("could not read path: " + error.toString()); }) .finally(function() { //resolve async job after promise of subprocess of finding files has been resolved return done(); }); //check if item is a file, that matches the filter and add it to files array } else if (item.indexOf(filter) >= 0) { files.push(path.join(startPath, item)); return done(); //file is no directory and does not match the filefilter -> don't do anything } else { return done(); } }) .catch(function(error){ ideferred.reject("Could not stat: " + error.toString()); }); }, function() { return ideferred.resolve(); //async each has finished, so resolve inner deferred }); return ideferred.promise; }).then(function() { //here you could do anything with the files of this recursion step (otherwise you would only need ONE deferred) return deferred.resolve(files); //resolve main deferred }).catch(function(error) { deferred.reject("Could not read dir: " + error.toString()); return }); return deferred.promise; } findFiles(process.env.START, process.env.FILTER, []) .then(function(files){ console.log(files); }) .catch(function(error){ console.log("Problem finding files: " + error); })
fuente
Instalar en pc
puede instalar este paquete walk-sync por
Uso
const walkSync = require("walk-sync"); const paths = walkSync("./project1/src", {globs: ["**/*.html"]}); console.log(paths); //all html file path array
fuente
Publicación anterior, pero ES6 ahora maneja esto fuera de la caja con el
includes
método.let files = ['file.json', 'other.js']; let jsonFiles = files.filter(file => file.includes('.json')); console.log("Files: ", jsonFiles) ==> //file.json
fuente
file.readdirSync
y necesitaba una forma sencilla de filtrar archivos por extensión. Creo que esto responde parte de la pregunta en este hilo, pero tal vez no todo. Todavía vale la pena considerarlo.