I\'d like to find all *.html files in src folder and all its sub folders using nodejs. What is the best way to do it?
var folder = \'/project1/src\';
var ex
You can use OS help for this. Here is a cross-platform solution:
1. The bellow function uses ls
and dir
and does not search recursively but it has relative paths
var 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. The bellow function uses find
and dir
, searches recursively but on windows it has absolute paths
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);
})
my two pence, using map in place of 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);
Take a look into file-regex
let findFiles = require('file-regex')
let pattern = '\.js'
findFiles(__dirname, pattern, (err, files) => {
console.log(files);
})
This above snippet would print all the js
files in the current directory.
The following code does a recursive search inside ./ (change it appropriately) and returns an array of absolute file names ending with .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);
I just noticed, you are using sync fs methods, that might block you application, here is a promise-based async way using async and q, you can execute it with START=/myfolder FILTER=".jpg" node myfile.js, assuming you put the following code in a file called 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);
})
Old post but ES6 now handles this out of the box with the includes
method.
let files = ['file.json', 'other.js'];
let jsonFiles = files.filter(file => file.includes('.json'));
console.log("Files: ", jsonFiles) ==> //file.json