我有一种实用的方法来读取目录并记录统计信息,如何以一种实用的方式递归获取所有文件夹树的统计信息?

问题描述

我可以使下面的代码仅读取目录,然后记录统计信息列表。 现在,我想知道如何遍历目录树并检索具有统计信息和文件路径的对象列表。

import fs from 'fs'
import {Task,traverse,concat,compose,chain,map,prop,List,filter } from './shared/functional.js';

// readDir :: String -> Task Error (List String)
const readDir = path => new Task((reject,result) => {
  fs.readdir(path,(err,data) => (err ? reject(err) : result(new List(data))));
});

// readDir :: String -> Task Error (Stat)
const readStat = filename => new Task((reject,result) => {
  fs.stat(filename,data) => (err ? reject(err) : result(data)));
});

const dirList = dir => chain(traverse(Task.of,compose(readStat,concat(dir))),readDir(dir),);

dirList('./shared/').fork(console.error,map(compose(console.log,prop('mtimeMs'))));

我猜我需要使用isDirectory来检查是否应该进入树的内部。但是他们我的问题是如何构造对象以及如何返回未嵌套的列表?

编辑:我现在不遵循https://mostly-adequate.gitbooks.io/mostly-adequate-guide/

中的类型和助手使用任何库

EDIT2:我提出了以下建议:

import fs from 'fs'
import {Task,filter,Maybe,identity,Either,curry } from './shared/functional.js';

// readDir :: String -> Task Error (List String)
const readDir = path => new Task((reject,data) => (err ? reject(err) : result(data)));
});

const isDir = curry((dir,stat) => {
  return stat.isDirectory()
    // eslint-disable-next-line no-use-before-define
    ? dirListAll(dir)
    : stat;
});

const dirListAll = dir => chain(traverse(Task.of,compose(map(isDir(dir)),readStat,);

现在我已经说明了方案,在此示例中,我有一个目录,其中有6个项目,其中有2个文件夹。所以我得到一个包含4个统计信息和2个任务的列表。

Task {fork: ƒ} 0 (6) [Task,Stats,Task,Stats]

可以在其中包含列表的后面,我现在需要除去外部函子,我可能再次尝试使用遍历链。但还没有成功。 再次感谢。

解决方法

您可能已经注意到,回调和循环不能很好地结合在一起。要解决此问题,我建议使用util.promisify。完成后,您可以轻松编写如下异步函数:

async function traverse(names,callback) {
  for (let name of names) {
    let s = await stat(name);
    if (s.isDirectory())
      await traverse( (await readdir(name)).map(x => path.join(name,x)),callback );
    else
      callback(name);
  }
}