Eu gostaria de encontrar todos os arquivos * .html na pasta src e todas as suas subpastas usando nodejs. Qual a melhor maneira de fazer isso?
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);
Acho que muitos desenvolvedores deveriam ter uma solução excelente e testada e é melhor usá-la do que escrever uma sozinho.
node.js
find
file-extension
Nicolas S.Xu
fonte
fonte
Respostas:
node.js, função simples 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');
adicione RegExp se quiser ficar mais sofisticado e um retorno de chamada para torná-lo 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); });
fonte
eu gosto de usar o pacote glob :
const glob = require('glob'); glob(__dirname + '/**/*.html', {}, (err, files)=>{ console.log(files) })
fonte
O quê, espera aí ?! ... Ok, talvez isso faça mais sentido para outras pessoas também.
[ nodejs 7 veja bem]
fs = import('fs'); let dirCont = fs.readdirSync( dir ); let files = dirCont.filter( function( elm ) {return elm.match(/.*\.(htm?html)/ig);});
Faça o que quer que seja com regex, torne-o um argumento que você definiu na função com um padrão etc.
fonte
wl
faz todo o sentido. Além disso, a importação para fs está faltando. As três linhas de que você precisa são: 1.const fs = require('fs');
2.const dirCont = fs.readdirSync( dir );
3.const files = dirCont.filter( ( elm ) => /.*\.(htm?html)/gi.test(elm) );
Com base no código do Lucio, fiz um módulo. Ele retornará uma distância com todos os arquivos com extensões específicas em um. Basta postar aqui caso alguém precise.
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;
fonte
Você pode usar o Filehound para fazer isso.
Por exemplo: encontre todos os arquivos .html em / 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 mais informações (e exemplos), verifique os documentos: https://github.com/nspragg/filehound
Isenção de responsabilidade : eu sou o autor.
fonte
Eu olhei as respostas acima e misturei esta versão que funciona para mim:
function getFilesFromPath(path, extension) { let files = fs.readdirSync( path ); return files.filter( file => file.match(new RegExp(`.*\.(${extension})`, 'ig'))); } console.log(getFilesFromPath("./testdata", ".txt"));
Este teste retornará uma matriz de nomes de arquivos dos arquivos encontrados na pasta no caminho
./testdata
. Trabalhando no nó versão 8.11.3.fonte
.*\.(${extension})$
Você pode usar a ajuda do sistema operacional para isso. Aqui está uma solução de plataforma cruzada:
1. A função abaixo usa
ls
edir
e não pesquisa recursivamente, mas tem caminhos relativosvar 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. A função abaixo usa
find
edir
, pesquisa recursivamente, mas no windows tem caminhos absolutosvar 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); })
fonte
O código a seguir faz uma pesquisa recursiva dentro de ./ (altere-o apropriadamente) e retorna uma matriz de nomes de arquivos absolutos terminando com .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);
fonte
Não é possível adicionar um comentário devido à reputação, mas observe o seguinte:
Usar fs.readdir ou node-glob para localizar um conjunto curinga de arquivos em uma pasta de 500.000 arquivos levou cerca de 2s. Usar exec com DIR demorou ~ 0,05s (não recursivo) ou ~ 0,45s (recursivo). (Eu estava procurando por ~ 14 arquivos correspondentes ao meu padrão em um único diretório).
Até agora, não consegui encontrar nenhuma implementação de nodejs que use curinga de SO de baixo nível em busca de eficiência. Mas o código baseado em DIR / ls acima funciona maravilhosamente no Windows em termos de eficiência. O linux find, entretanto, provavelmente será muito lento para diretórios grandes.
fonte
meus dois pence, usando map em vez 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);
fonte
Dê uma olhada em file-regex
let findFiles = require('file-regex') let pattern = '\.js' findFiles(__dirname, pattern, (err, files) => { console.log(files); })
Este trecho acima imprimirá todos os
js
arquivos no diretório atual.fonte
Eu só percebi, você está usando métodos fs de sincronização, que pode bloquear a sua aplicação, aqui é um assíncrono maneira usando baseado promessa- assíncrono e q , você pode executá-lo com start = / MyFolder myfile.js FILTER = "jpg". Nó, presumindo que você coloque o seguinte código em um arquivo chamado 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); })
fonte
Instalar
você pode instalar este pacote walk-sync por
Uso
const walkSync = require("walk-sync"); const paths = walkSync("./project1/src", {globs: ["**/*.html"]}); console.log(paths); //all html file path array
fonte
Postagem antiga, mas o ES6 agora trata disso fora da caixa com o
includes
método.let files = ['file.json', 'other.js']; let jsonFiles = files.filter(file => file.includes('.json')); console.log("Files: ", jsonFiles) ==> //file.json
fonte
file.readdirSync
e precisava de uma maneira simples de filtrar arquivos por extensão. Acho que isso responde parte da pergunta neste tópico, mas talvez não tudo. Ainda vale a pena considerar.