从文件系统创建对象树

Create object tree from file system

我需要从 CL 参数中获取目录路径并创建一个对象树,其中包含所选目录的文件结构。

如果它是一个文件,它的值应该是真实的。如果它是一个目录,我应该对该目录执行相同的操作(我认为最好的方法是递归)。

输出应该如下所示:

{
  file.txt: true,
  directory: {
    one.txt: true,
    two.txt: true,
    ...
  }
  ...
}

到目前为止,我尝试了它的递归版本,但它失败了,不知道为什么。我认为这是因为我没有正确处理代码的异步部分。这是我的代码:

const fs = require("fs");

const basePath = process.argv[2]; //Getting the path (it works)
const result = {};

//Function to check my path is exist and it's a directory
const isDirectory = path => {
  return new Promise((resolve, reject) => {
    fs.lstat(path, (err, stats) => {
      if (err) reject("No such file or Directory");
      resolve(stats.isDirectory());
    });
  });
};

//Recursive function that should create the object tree of the file system
const createTree = (path, target) => {
  return new Promise((resolve, reject) => {
    reject("Promise Oops...");
    fs.readdir(path, (err, data) => {
      data.forEach(item => {
        const currentLocation = `${path}/${item}`;
        isDirectory(currentLocation)
          .then(isDir => {
            if (!isDir) {
              target[item] = true;
              return;
            }

            target[item] = {};
            resolve(createTree(currentLocation, target[item]));
          })
          .catch(err => console.log("Oops in then..."));
      });
    });
  });
};

//Consuming the createTree function
(async () => {
  try {
    const res = await createTree(basePath, result);
    console.log(res);
  } catch (err) {
    console.log("Oops consume...");
  }
})();

您可以使用 fs.promises 而不是 fs 基于回调的方法,这提高了可读性并帮助您轻松找到错误。 您正在记录未定义的 createTree 函数返回的内容。您应该记录 result 对象以查看您想要的结果。

const fs = require("fs");

const basePath = process.argv[2]; //Getting the path (it works)
const result = {};

//Function to check my path is exist and it's a directory
const isDirectory = async (path) => {
  try {
    const stats = await fs.promises.lstat(path);
    return stats.isDirectory();
  } catch (error) {
    throw new Error("No such file or Directory");
  }
};

//Recursive function that should create the object tree of the file system
const createTree = async (path, target) => {
  const data = await fs.promises.readdir(path);
  for (const item of data) {
    const currentLocation = `${path}/${item}`;
    const isDir = await isDirectory(currentLocation);
    if (!isDir) {
      target[item] = true;
      continue;
    }
    target[item] = {};
    await createTree(currentLocation, target[item]);
  }
};

//Consuming the createTree function
(async () => {
  try {
    await createTree(basePath, result);
    console.log(result);
  } catch (error) {
    console.log(error.message);
  }
})();

fs/promises 和 fs.Dirent

这是一个使用 Node 的快速 fs.Dirent objects and fs/promises 模块的高效 non-blocking 程序。这种方法允许您跳过每条路径上浪费的 fs.existfs.stat 调用 -

// main.js

import { readdir } from "fs/promises"
import { join, basename } from "path"

async function* tokenise (path = ".")
{ yield { dir: path }
  for (const dirent of await readdir(path, { withFileTypes: true }))
    if (dirent.isDirectory())
      yield* tokenise(join(path, dirent.name))
    else
      yield { file: join(path, dirent.name) }
  yield { endDir: path }
}

async function parse (iter = empty())
{ const r = [{}]
  for await (const e of iter)
    if (e.dir)
      r.unshift({})
    else if (e.file)
      r[0][basename(e.file)] = true
    else if (e.endDir)
      r[1][basename(e.endDir)] = r.shift()
  return r[0]
}

async function* empty () {}

现在createTree只是tokeniseparse的组合-

const createTree = (path = ".") =>
  parse(tokenise(path))

createTree(".")
  .then(r => console.log(JSON.stringify(r, null, 2)))
  .catch(console.error)

让我们获取一些示例文件,以便我们可以看到它正在运行 -

$ yarn add immutable     # (just some example package)
$ node main.js
{
  ".": {
    "main.js": true,
    "node_modules": {
      ".yarn-integrity": true,
      "immutable": {
        "LICENSE": true,
        "README.md": true,
        "contrib": {
          "cursor": {
            "README.md": true,
            "__tests__": {
              "Cursor.ts.skip": true
            },
            "index.d.ts": true,
            "index.js": true
          }
        },
        "dist": {
          "immutable-nonambient.d.ts": true,
          "immutable.d.ts": true,
          "immutable.es.js": true,
          "immutable.js": true,
          "immutable.js.flow": true,
          "immutable.min.js": true
        },
        "package.json": true
      }
    },
    "package.json": true,
    "yarn.lock": true
  }
}

希望您喜欢这篇文章post。有关使用异步生成器的更多说明和其他方法,请参阅