关于使用fs.readdir进行异步目录搜索有什么想法吗?我意识到我们可以引入递归,并调用read目录函数来读取下一个目录,但我有点担心它不是异步的…
什么好主意吗?我已经看了node-walk,它很棒,但它不能像readdir那样只给我数组中的文件。虽然
寻找这样的输出…
['file1.txt', 'file2.txt', 'dir/file3.txt']
关于使用fs.readdir进行异步目录搜索有什么想法吗?我意识到我们可以引入递归,并调用read目录函数来读取下一个目录,但我有点担心它不是异步的…
什么好主意吗?我已经看了node-walk,它很棒,但它不能像readdir那样只给我数组中的文件。虽然
寻找这样的输出…
['file1.txt', 'file2.txt', 'dir/file3.txt']
当前回答
qwtel的答案变体,在TypeScript中
import { resolve } from 'path';
import { readdir } from 'fs/promises';
async function* getFiles(dir: string): AsyncGenerator<string> {
const entries = await readdir(dir, { withFileTypes: true });
for (const entry of entries) {
const res = resolve(dir, entry.name);
if (entry.isDirectory()) {
yield* getFiles(res);
} else {
yield res;
}
}
}
其他回答
使用承诺(Q)以函数式风格解决此问题:
var fs = require('fs'),
fsPath = require('path'),
Q = require('q');
var walk = function (dir) {
return Q.ninvoke(fs, 'readdir', dir).then(function (files) {
return Q.all(files.map(function (file) {
file = fsPath.join(dir, file);
return Q.ninvoke(fs, 'lstat', file).then(function (stat) {
if (stat.isDirectory()) {
return walk(file);
} else {
return [file];
}
});
}));
}).then(function (files) {
return files.reduce(function (pre, cur) {
return pre.concat(cur);
});
});
};
它返回一个数组的promise,所以你可以这样使用它:
walk('/home/mypath').then(function (files) { console.log(files); });
因为每个人都应该写自己的,所以我写了一个。
步行(dir, cb, endCb) cb(文件) 零endCb (err |)
脏
module.exports = walk;
function walk(dir, cb, endCb) {
var fs = require('fs');
var path = require('path');
fs.readdir(dir, function(err, files) {
if (err) {
return endCb(err);
}
var pending = files.length;
if (pending === 0) {
endCb(null);
}
files.forEach(function(file) {
fs.stat(path.join(dir, file), function(err, stats) {
if (err) {
return endCb(err)
}
if (stats.isDirectory()) {
walk(path.join(dir, file), cb, function() {
pending--;
if (pending === 0) {
endCb(null);
}
});
} else {
cb(path.join(dir, file));
pending--;
if (pending === 0) {
endCb(null);
}
}
})
});
});
}
我喜欢上面chjj的答案,如果没有那个开始,我就无法创建我的并行循环版本。
var fs = require("fs");
var tree = function(dir, done) {
var results = {
"path": dir
,"children": []
};
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) {
fs.stat(dir + '/' + file, function(err, stat) {
if (stat && stat.isDirectory()) {
tree(dir + '/' + file, function(err, res) {
results.children.push(res);
if (!--pending){ done(null, results); }
});
} else {
results.children.push({"path": dir + "/" + file});
if (!--pending) { done(null, results); }
}
});
});
});
};
module.exports = tree;
我也创建了一个Gist。欢迎评论。我仍然在NodeJS领域起步,所以这是我希望学到更多的一种方式。
只是简单的散步
let pending = [baseFolderPath]
function walk () {
pending.shift();
// do stuffs width pending[0] and change pending items
if (pending[0]) walk(pending[0])
}
walk(pending[0])
简单,基于异步承诺
const fs = require('fs/promises');
const getDirRecursive = async (dir) => {
try {
const items = await fs.readdir(dir);
let files = [];
for (const item of items) {
if ((await fs.lstat(`${dir}/${item}`)).isDirectory()) files = [...files, ...(await getDirRecursive(`${dir}/${item}`))];
else files.push({file: item, path: `${dir}/${item}`, parents: dir.split("/")});
}
return files;
} catch (e) {
return e
}
};
用法:await getDirRecursive("./public");