如何创建嵌套对象目录名称直到找到文件

How to create nested object directory name till it found a file

如果没有任何目录,我正在制作一个包含文件目录和文件名的嵌套对象

预期:

{ dir_name : "test",
  sub_dir : {dir_name : "test2",
             sub_dir : {dir_name : "test3".
                        sub_dir: [0001.dcm, 0002.dcm, 003.dcm]}}
}

我的结果:

{ dir_name: 'test', sub_dir: Promise { <pending> } }

我的代码:

async function make_dir(FilePath){
  return new Promise((resolve, reject) => {
    fs.readdir(FilePath, async (err,files) => {
      var arr = [];
      files.forEach((file) => {
        if (!file.includes(".dcm")){
          var container = { dir_name: file,
                        sub_dir: {}}
          container.sub_dir =  make_dir(FilePath + file + '/')
          resolve(container)
        }
        else{
          arr.push(file);
        }
      });
      resolve(arr)
    })
  })
}

建议的结构无效,因为一个目录可以有一个 或更多 个子目录 -

{ 
  dir: "foo",
  sub_dir: { ... },
  sub_dir: { ... }, // cannot reuse "sub_dir" key
}

这里有一个替代方案,可以像这样构建一棵树 -

{ 
  "test1":
    {
      "test2":
         {
            "test3":
              {    
                "0001.dcm": true,
                "0002.dcm": true,
                "003.dcm": true
              }
         }
    }
}

fs/promises 和 fs.Dirent

这是一个使用 Node 的快速 fs.Dirent objects and fs/promises 模块的高效、非阻塞程序。这种方法将问题的关注点分开,并允许您跳过每条路径上浪费的 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。有关使用异步生成器的更多说明和其他方法,请参阅