Javascript 从文件系统创建对象树

Javascript 从文件系统创建对象树,javascript,node.js,object,recursion,filesystems,Javascript,Node.js,Object,Recursion,Filesystems,我需要从CL参数中获取目录的路径,并创建一个对象树,其中包含所选目录的文件结构 如果是文件,则其值应为true。如果它是一个目录,我应该对这个目录做同样的操作,我认为最好的方法是递归 输出应如下所示: { file.txt: true, directory: { one.txt: true, two.txt: true, ... } ... } 到目前为止,我尝试了递归版本,但失败了,不知道为什么。我想这是因为我没有正确处理代码的异步部分。这是我的密码:

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

如果是文件,则其值应为true。如果它是一个目录,我应该对这个目录做同样的操作,我认为最好的方法是递归

输出应如下所示:

{
  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函数返回的未定义内容。您应该记录结果对象以查看所需的结果

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方法,这样可以提高可读性并帮助您轻松发现错误。 您正在记录createTree函数返回的未定义内容。您应该记录结果对象以查看所需的结果

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.exist或fs.stat调用-

//main.js 从fs/promises导入{readdir} 从路径导入{join,basename} 异步函数*令牌化路径=。 {yield{dir:path} 对于await readdirpath的常量,{withFileTypes:true} if dirent.isDirectory yield*tokenisejoinpath,dirent.name 其他的 产生{file:joinpath,dirent.name} 产生{endDir:path} } 异步函数parse iter=empty {const r=[{}] 国际热核实验堆的等待常数 如果e.dir r、 取消移位{} 否则,如果是e.file r[0][basenamee.file]=true 否则,如果e.endDir r[1][basenamee.endDir]=r.shift 返回r[0] } 异步函数*空{} 现在createTree只是令牌化和解析的组合-

const createTree=路径=。=> 解析令牌路径 创建树。 .thenr=>console.logJSON.stringifyr,null,2 .catchconsole.error 让我们获取一些示例文件,这样我们就可以看到它在工作-

$THEAN添加不可变的示例包 $node main.js { .: { main.js:没错, 节点单元模块:{ .纱线完整性:正确, 不变的:{ 许可证:是的, 是的, 承包商:{ 光标:{ 是的, __测试:{ Cursor.ts.skip:true }, 索引d.ts:正确, index.js:true } }, 地区:{ immutable-nonambient.d.ts:true, 不可变的d.ts:正确, immutable.es.js:true, immutable.js:true, immutable.js.flow:true, immutable.min.js:true }, package.json:true } }, package.json:true, 洛克:没错 } } 我希望你喜欢读这篇文章。有关使用异步生成器的附加说明和其他方法,请参阅。

fs/promises和fs.Dirent

这是一个使用节点的快速对象和模块的高效、无阻塞程序。这种方法允许您跳过每个路径上浪费的fs.exist或fs.stat调用-

//main.js 从fs/promises导入{readdir} 从路径导入{join,basename} 异步函数*令牌化路径=。 {yield{dir:path} 对于await readdirpath的常量,{withFileTypes:true} if dirent.isDirectory yield*tokenisejoinpath,dirent.name 其他的 产生{file:joinpath,dirent.name} 产生{endDir:path} } 异步函数parse iter=empty {const r=[{}] 国际热核实验堆的等待常数 如果e.dir r、 取消移位{} 否则,如果是e.file r[0][basenamee.file]=true 否则,如果e.endDir r[1][basenamee.endDir]=r.shift 返回r[0] } 异步函数*空{} 现在createTree只是令牌化和解析的组合-

const createTree=路径=。=> 解析令牌路径 创建树。 .thenr=>console.logJSON.stringifyr,null,2 .catchconsole.error 让我们获取一些示例文件,这样我们就可以看到它在工作-

$THEAN添加不可变的示例包 $node main.js { .: { main.js:没错, 节点单元模块:{ .纱线完整性:正确, 不变的:{ 许可证:是的, 是的, 承包商:{ 光标:{ 是的, __测试:{ Cursor.ts.skip:true }, 索引d.ts:正确, index.js:true } }, 地区:{ immutable-nonambient.d.ts:true, 不可变的d.ts:正确, immutable.es.js:true, immutable.js:true, immutable.js.flow:true, immutable.min.js:true }, package.json:true } }, package.json:true, 洛克:没错 } } 我希望你喜欢读这篇文章。增加
解释和其他使用异步生成器的方法,请参阅。

谢谢,但它仅适用于一个目录,它将进入第一个目录并退出函数。谢谢,但它仅适用于一个目录,它将进入第一个目录并退出函数。