关于使用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']
当前回答
为了好玩,这里有一个基于流的版本,它与highland.js streams库一起工作。作者之一是维克多·伍。
###
directory >---m------> dirFilesStream >---------o----> out
| |
| |
+--------< returnPipe <-----------+
legend: (m)erge (o)bserve
+ directory has the initial file
+ dirListStream does a directory listing
+ out prints out the full path of the file
+ returnPipe runs stat and filters on directories
###
_ = require('highland')
fs = require('fs')
fsPath = require('path')
directory = _(['someDirectory'])
mergePoint = _()
dirFilesStream = mergePoint.merge().flatMap((parentPath) ->
_.wrapCallback(fs.readdir)(parentPath).sequence().map (path) ->
fsPath.join parentPath, path
)
out = dirFilesStream
# Create the return pipe
returnPipe = dirFilesStream.observe().flatFilter((path) ->
_.wrapCallback(fs.stat)(path).map (v) ->
v.isDirectory()
)
# Connect up the merge point now that we have all of our streams.
mergePoint.write directory
mergePoint.write returnPipe
mergePoint.end()
# Release backpressure. This will print files as they are discovered
out.each H.log
# Another way would be to queue them all up and then print them all out at once.
# out.toArray((files)-> console.log(files))
其他回答
有一个名为cup-readdir的新模块,可以快速递归地搜索目录。它使用异步承诺,在处理深层目录结构时性能优于许多流行的模块。
它可以返回数组中的所有文件,并根据它们的属性对它们进行排序,但缺乏文件过滤和进入符号链接目录等功能。这对于只想从目录中获取每个文件的大型项目非常有用。这里是他们项目主页的链接。
使用承诺(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); });
看看装载机 https://npmjs.org/package/loaddir
npm无处不在
loaddir = require('loaddir')
allJavascripts = []
loaddir({
path: __dirname + '/public/javascripts',
callback: function(){ allJavascripts.push(this.relativePath + this.baseName); }
})
如果还需要扩展名,可以使用fileName而不是baseName。
一个额外的好处是,它也会监视文件,并再次调用回调。有大量的配置选项使它非常灵活。
我只是在短时间内用加载器从红宝石重造了守卫宝石
另一个答案,但这次使用的是TypeScript:
/** * Recursively walk a directory asynchronously and obtain all file names (with full path). * * @param dir Folder name you want to recursively process * @param done Callback function, returns all files with full path. * @param filter Optional filter to specify which files to include, * e.g. for json files: (f: string) => /.json$/.test(f) */ const walk = ( dir: string, done: (err: Error | null, results ? : string[]) => void, filter ? : (f: string) => boolean ) => { let results: string[] = []; fs.readdir(dir, (err: Error, list: string[]) => { if (err) { return done(err); } let pending = list.length; if (!pending) { return done(null, results); } list.forEach((file: string) => { file = path.resolve(dir, file); fs.stat(file, (err2, stat) => { if (stat && stat.isDirectory()) { walk(file, (err3, res) => { if (res) { results = results.concat(res); } if (!--pending) { done(null, results); } }, filter); } else { if (typeof filter === 'undefined' || (filter && filter(file))) { results.push(file); } if (!--pending) { done(null, results); } } }); }); }); };
Filehound库是另一种选择。它将递归地搜索给定目录(默认为工作目录)。它支持各种过滤器、回调、承诺和同步搜索。
例如,搜索当前工作目录中的所有文件(使用回调):
const Filehound = require('filehound');
Filehound.create()
.find((err, files) => {
if (err) {
return console.error(`error: ${err}`);
}
console.log(files); // array of files
});
或承诺,并指定特定的目录:
const Filehound = require('filehound');
Filehound.create()
.paths("/tmp")
.find()
.each(console.log);
更多的用例和使用示例请参考文档:https://github.com/nspragg/filehound
声明:我是作者。