本文概述
- A.使用自定义代码段
- B.使用readdirp模块
- C.使用klaw和klaw-sync模块
在本文中, 我们将向你展示如何递归循环目录, 以使用3种不同方法(自定义代码段或使用开放源代码模块)列出其所有内容。
A.使用自定义代码段【如何在Node.js中递归读取目录】如果要递归地遍历Node.js中的目录, 则不需要模块来实现它, 因为可以使用非常简单的递归函数。以下filewalker函数将为你解决问题。它期望作为第一个参数的字符串具有将要递归浏览的文件夹的路径, 而作为第二个参数的期望是当Providen路径中没有更多目录时执行的函数(回调)。回调接收2个参数, 第一个为错误, 结果数组包含文件和子目录的所有混合路径。
注意如果你只需要忽略所有文件夹并仅检索文件的路径, 则可以轻松地注释掉将文件路径存储在代码段内的行中。
const fs = require('fs');
const path = require('path');
/** * Explores recursively a directory and returns all the filepaths and folderpaths in the callback. * * @see http://stackoverflow.com/a/5827895/4241030 * @param {String} dir * @param {Function} done */function filewalker(dir, done) {let 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 directory, execute a recursive callif (stat &
&
stat.isDirectory()) {// Add directory to array [comment if you need to remove the directories from the array]results.push(file);
filewalker(file, function(err, res){results = results.concat(res);
if (!--pending) done(null, results);
});
} else {results.push(file);
if (!--pending) done(null, results);
}});
});
});
};
它的用法非常简单:
filewalker("./some-existent-path", function(err, data){if(err){throw err;
}// ["c://some-existent-path/file.txt", "c:/some-existent-path/subfolder"]console.log(data);
});
如果你不想依靠模块直接在代码中实现非常简单的功能, 则此解决方案是完美的。
B.使用readdirp模块如果你的代码不是那么简单, 那么由于代码的复杂性, 仅提供一个摘要的解决方案可能对你来说不够。在这种情况下, 你可以使用readdirp模块, 是的, readdirp不是readdir。 readdirp是一个非常有用的模块, 它公开了Node.js文件系统模块中可用的readdir函数的递归版本, 此外还公开了流api。
要在你的项目中安装此模块, 请在终端中执行以下命令:
npm install readdirp
使用此模块的优势非常明显, 它不像我们在本文中介绍的第一个解决方案那么简单。除了允许你设置深度(在Providen目录中要探索的子文件夹的最大值)之外, 该模块还允许你通过文件扩展名和目录名称来过滤递归探索。它以以下方式工作, 你需要使用readdirp模块, 该模块基本上是一个函数。使用此功能, 你将能够递归遍历文件夹路径, 它需要一个指定设置的对象, 你可以在此处查看readdirp的所有可用选项:
var settings = {root: './a-folder-to-explore', entryType: 'all', // Filter files with js and json extensionfileFilter: [ '*.js', '*.json' ], // Filter by directorydirectoryFilter: [ '!.git', '!*modules' ], // Work with files up to 1 subdirectory deepdepth: 1};
基本上, 你只需要提供表明将浏览哪个目录的root属性。
该模块提供了两种使用方式, 第一种是与回调一起使用:
// Import the modulevar readdirp = require('readdirp');
var settings = {root: './your-folder-path', entryType: 'all'};
// In this example, this variable will store all the paths of the files and directories inside the providen pathvar allFilePaths = [];
// Iterate recursively through a folderreaddirp(settings, // This callback is executed everytime a file or directory is found inside the providen pathfunction(fileInfo) {// Store the fullPath of the file/directory in our custom array allFilePaths.push(fileInfo.fullPath);
}, // This callback is executed once function (err, res) {if(err){throw err;
}// An array with all the fileEntry objects of the folder // console.log(res);
console.log(allFilePaths);
// ["c:/file.txt", ""]});
或通过流API:
// Import the modulevar readdirp = require('readdirp');
var settings = {root: './', entryType: 'all'};
// In this example, this variable will store all the paths of the files and directories inside the providen pathvar allFilePaths = [];
// Iterate recursively through a folderreaddirp(settings).on('data', function (entry) {// execute everytime a file is found in the providen directory// Store the fullPath of the file/directory in our custom array allFilePaths.push(entry.fullPath);
}).on('warn', function(warn){console.log("Warn: ", warn);
}).on('error', function(err){console.log("Error: ", err);
}).on('end', function(){console.log(allFilePaths);
// ["c:/file.txt", "c:/other-file.txt" ...]});
每个fileEntry对象都具有以下结构, 因此, 你不仅将获得完整路径, 而且还将获得有关文件或目录的更多有用信息:
{name: 'index.js', path: 'node_modules\\string_decoder\\index.js', fullPath: 'C:\\Users\\sdkca\\Desktop\\node-workspace\\node_modules\\string_decoder\\index.js', parentDir: 'node_modules\\string_decoder', fullParentDir: 'C:\\Users\\sdkca\\Desktop\\node-workspace\\node_modules\\string_decoder', stat:Stats {dev: -469691281, mode: 33206, nlink: 1, uid: 0, gid: 0, rdev: 0, blksize: undefined, ino: 562949954035272, size: 7796, blocks: undefined, atime: 2017 - 03 - 31T18: 27:30.703Z, mtime: 2017 - 03 - 31T18: 27:30.724Z, ctime: 2017 - 03 - 31T18: 27:30.724Z, birthtime: 2017 - 03 - 31T18: 27:30.703Z }};
有关更多信息, 请在此处访问Github中的模块存储库。
C.使用klaw和klaw-sync模块最初, 很多开发人员过去都依赖于扳手模块(很多人仍然依赖), 但是现在正式不赞成使用它, 并且我们喜欢推广标准, 你不应该再使用它(我们不禁止使用它, 因此随时可以如果你愿意, 请探索该模块, 但请考虑一下是否已弃用)。该项目现在建议使用fs-extra模块, 但是该模块不再支持walk()和walkSync()函数(这是开发人员为什么使用扳手模块递归浏览目录的原因)。
由于递归功能不再可用, 因此fs-extra模块建议使用klaw模块。此模块使用最初从fs-extra模块提取的Readable流接口公开异步Node.js文件系统walker。
要安装此模块, 请在终端中执行以下命令:
npm install klaw
Klaw非常易于使用和可定制。要递归遍历目录, 请使用以下代码段:
// Import the klaw modulevar klaw = require('klaw');
// an array to store the folder and files insidevar items = [];
var directoryToExplore = "./some-folder";
klaw(directoryToExplore).on('data', function (item) {items.push(item.path)}).on('end', function () {console.log(items);
}).on('error', function (err, item) {console.log(err.message)console.log(item.path) // the file the error occurred on});
由于它是异步的, 因此你需要依靠end回调对Providen目录中找到的文件和目录列表进行任何操作。
有关异步klaw模块的更多信息, 请访问Github上的官方存储库。
如果你需要相同的功能但需要同步, 则可以使用klaw-sync模块。 klaw-sync是Node.js递归文件系统walker, 它是klaw的同步副本。它递归列出目录中的所有文件和目录, 并返回一个对象数组, 每个对象都有两个属性:path和stats。 path是文件或目录的完整路径, 而stats是fs.Stats的实例。
要安装此模块, 请在终端中执行以下命令:
npm install klaw-sync
klaw的同步版本与异步版本一样易于使用, 但是比其对应版本更具可定制性。你可以使用以下代码段浏览目录:
// Require the modulevar klawSync = require('klaw-sync');
// Create an empty variable to be accesible in the closurevar paths;
// The directory that you want to explorevar directoryToExplore = "./folder-to-explore";
try {paths = klawSync(directoryToExplore);
} catch (err) {console.error(err);
}// [//{path:"c:/file.txt", stats: {..File information..}}, //{path:"c:/file.txt", stats: {..File information..}}, //{path:"c:/file.txt", stats: {..File information..}}, // ]console.log(paths);
klaw-sync允许你按扩展名(名称)过滤目录和文件。此外, 你可以通过设置以下选项来仅搜索目录或文件:
var klawSync = require('klaw-sync');
var directoryToExplore = "./some-folder";
var files = klawSync(directoryToExplore, {nodir: true});
// [//{path:"c:/file.txt", stats: {..File information..}}, //{path:"c:/file2.txt", stats: {..File information..}}, //{path:"c:/file3.txt", stats: {..File information..}}, // ]console.log(files);
var paths = klawSync(directoryToExplore, {nofile: true});
// [//{path:"c:/folder", stats: {..Folder information..}}, //{path:"c:/folder2", stats: {..Folder information..}}, //{path:"c:/folder3", stats: {..Folder information..}}, // ]console.log(paths);
有关同步爪模块的更多信息, 请访问Github上的官方存储库。
Klaw代表走动(但向后走), 事实证明(截至2017年1月25日), 在大多数情况下, klaw和klaw-sync比其他模块快。
编码愉快!
推荐阅读
- 如何选择最佳的Node.js框架(Express.js,Koa.js或Sails.js)
- 如何轻松在Node.js中将事件发射器与ES5和ES6结合使用
- 如何使用Node.js中的文件系统(fs)模块创建文件
- 如何在Node.js中将文本转换(合成)为语音
- CRM如何提高IT公司的利率
- 如何在Node.js中使用nodemailer发送电子邮件(gmail,Outlook和Zoho)
- 最新的Zoom安全漏洞(你需要了解的内容)
- 地理编码将如何塑造未来的技术和服务
- 使你的网站闪电般飞速的10条性能提示