我想使用nodejs找到src文件夹及其所有子文件夹中的所有* .html文件。最好的方法是什么?
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);
我认为很多开发人员应该拥有优秀且经过测试的解决方案,并且使用它比自己编写解决方案更好。
答案 0 :(得分:54)
node.js,递归简单函数:
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');
如果你想获得想象力,可以添加RegExp,并使用回调来使其成为通用的。
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);
});
答案 1 :(得分:34)
我喜欢使用glob package:
const glob = require('glob');
glob(__dirname + '/**/*.html', {}, (err, files)=>{
console.log(files)
})
答案 2 :(得分:15)
什么,坚持下去?! ...好吧,也许这对其他人来说也更有意义。
[ nodejs 7 请注意]
let dirCont = wl.fs.readdirSync( dir );
let files = dirCont.filter( function( elm ) {return elm.match(/.*\.(htm?html)/ig);});
使用正则表达式执行任何操作,使其成为您在函数中使用默认值等设置的参数。
答案 3 :(得分:9)
根据Lucio的代码,我制作了一个模块。它将返回一个带有特定扩展名的所有文件。只需在此处发布,以防任何人需要它。
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;
答案 4 :(得分:8)
您可以使用 Filehound 执行此操作。
例如:找到/ tmp中的所有.html文件:
const Filehound = require('filehound');
Filehound.create()
.ext('html')
.paths("/tmp")
.find((err, htmlFiles) => {
if (err) return console.error("handle err", err);
console.log(htmlFiles);
});
有关详细信息(和示例),请查看文档: https://github.com/nspragg/filehound
免责声明:我是作者。
答案 5 :(得分:4)
我查看了以上答案,并将这个对我有用的版本混合在一起:
function getFilesFromPath(path, extension) {
let dir = fs.readdirSync( path );
return dir.filter( elm => elm.match(new RegExp(`.*\.(${extension})`, 'ig')));
}
console.log(getFilesFromPath("./testdata", ".txt"));
此测试将从路径./testdata
的文件夹中找到的文件返回文件名数组。正在使用8.11.3版的节点。
答案 6 :(得分:2)
以下代码在./内进行递归搜索(适当更改)并返回以.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);
答案 7 :(得分:1)
您可以使用OS帮助。这是一个跨平台的解决方案:
1。下面的函数使用ls
和dir
并且不会递归搜索,但它有相对路径
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。下面的函数使用find
和dir
,递归搜索但在窗口上它有绝对路径
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);
})
答案 8 :(得分:1)
我的两便士,使用地图代替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);
答案 9 :(得分:0)
我刚注意到,你正在使用同步fs方法,可能会阻止你的应用程序,这是一种基于承诺的异步方式,使用 async 和 q ,你可以执行它与START = / myfolder FILTER =&#34; .jpg&#34;节点myfile.js,假设您将以下代码放在名为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);
})
答案 10 :(得分:0)
let findFiles = require('file-regex')
let pattern = '\.js'
findFiles(__dirname, pattern, (err, files) => {
console.log(files);
})
以上代码段将打印当前目录中的所有js
个文件。
答案 11 :(得分:0)
您可以通过以下模块达到您的目标:
它允许您拥有一个json对象或代表给定路径树的字符串。 找到文件时,它还会回调,并提供几个过滤器和选项。
这是代码:
const dree = require('dree');
const files = [];
const fileCb = function(file) {
files.push(file.name);
}
dree.scan('path', { extensions: ['txt', 'html'] }, fileCb);
console.log(files); //Print all txt and html files found
答案 12 :(得分:0)
由于声誉而无法添加评论,但请注意以下几点:
使用fs.readdir或node-glob在500,000个文件的文件夹中查找通配符文件集大约需要2秒钟的时间。 与DIR一起使用exec花费了〜0.05s(非递归)或〜0.45s(递归)。 (我当时正在单个目录中查找〜14个与我的模式匹配的文件)。
到目前为止,我还没有找到任何使用低级OS通配符搜索效率的nodejs实现。但是,就效率而言,以上基于DIR / ls的代码在Windows中表现出色。 linux在大型目录中找到will likely be very slow。
答案 13 :(得分:0)
旧帖子,但是ES6现在使用includes
方法开箱即用。
let files = ['file.json', 'other.js'];
let jsonFiles = files.filter(file => file.includes('.json'));
console.log("Files: ", jsonFiles) ==> //file.json
答案 14 :(得分:0)
您可以通过以下方式安装此软件包walk-sync
yarn add walk-sync
const walkSync = require("walk-sync");
const paths = walkSync("./project1/src", {globs: ["**/*.html"]});
console.log(paths); //all html file path array
答案 15 :(得分:0)
您可以编辑此代码以适合您打算执行的操作。我为 nodejs IO 操作使用了同步版本,以便在 node 继续执行下一行代码之前返回结果:
const fs = require('fs');
const path = require('path');
// Path to the directory(folder) to look into
const dirPath = path.resolve(`${__dirname}../../../../../tests_output`);
// Read all files with .html extension in the specified folder above
const filesList = fs.readdirSync(dirPath, (err, files) => files.filter((e) => path.extname(e).toLowerCase() === '.html'));
// Read the content of the first file with .txt extension in the folder
const data = fs.readFileSync(path.resolve(`${__dirname}../../../../../tests_output/${filesList[0]}`), 'utf8');
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write(data);
return res.end();