我是Node js的新手,我有一项任务是通过扩展名为搜索文件创建cli实用程序。我写这个
const fs = require('fs');
const path = require('path');
let pathSupplied = './';
let extFilter = 'html';
function extension(element) {
let extName = path.extname(element);
return extName === '.' + extFilter;
};
let walk = function (dir, done) {
let result = []
fs.readdir(dir, function (err, list) {
list.forEach((item) => {
let itemPath = path.join(dir, item);
fs.stat(itemPath, (e, stats) => {
console.log(itemPath);
if (stats.isDirectory()) {
walk(itemPath);
} else {
list.filter(extension).forEach(function (value) {
console.log(value);
});
}
});
});
})
}
它有效,但不是我想要的方式。在输出中,我得到了带有html扩展名的文件,但是它们是重复的。我怎样才能解决这个问题?以及如何将结果写入数组?
这很自然地使用promise和async/await
,因为它使编码变得非常简单。我建议创建一个通用的walk()
函数,您可以将其传递给该回调函数,该回调函数将针对层次结构中的每个文件被调用。然后,您可以使用该回调来收集所需的任何结果。
这里是通用行走功能:
const fsp = require('fs').promises;
const path = require('path');
async function walk(dir, callback, results = []) {
let files = await fsp.readdir(dir, {withFileTypes: true});
let dirs = [];
for (let file of files) {
let fullPath = path.join(dir, file.name);
if (file.isFile()) {
let r = await callback(fullPath);
if (r !== undefined) {
results.push(r);
}
} else if (file.isDirectory()) {
// save this until we're done with files
dirs.push(fullPath);
}
}
for (let d of dirs) {
await walk(d, callback, results);
}
return results;
}
然后,您可以像这样使用它来累积具有特定扩展名的文件:
const targetExt = ".html";
const someTopDir = "D:/somepath/somedir";
walk(someTopDir, function(file) {
if (path.extname(file) === targetExt) {
return file;
}
}).then(results => {
console.log(results);
}).catch(err => {
console.log(err);
});
有关实现的一些注意事项:
withFileTypes
的较新readdir()
选项,该选项在每个文件上保存一个异步操作以测试它是否是目录walk()
函数返回一个承诺,该承诺将解析为回调返回的值数组。这意味着您可以像.map()
和.filter()
的组合一样使用它。输入数组是目录层次结构中所有文件的数组。如果您的回调返回undefined
,则该特定文件的输出中不存在任何内容(类似于.filter()
)。如果回调返回的不是undefined
,则该返回值将在输出数组中(类似于.map()
)。在此特定的回调实现中,它检查文件扩展名是否为匹配的扩展名。如果是这样,它将仅返回该文件名(以将其包含在输出中)。如果不是,它将不返回任何内容(这意味着返回值为undefined
),因此该文件的输出中不包含任何内容。实际上,它允许您同时执行.map()
和.filter()
。