I'm making a nested object that contains a file directory and file name if don't have any directory left
expected :
{ dir_name : "test",
sub_dir : {dir_name : "test2",
sub_dir : {dir_name : "test3".
sub_dir: [0001.dcm, 0002.dcm, 003.dcm]}}
}
my result:
{ dir_name: 'test', sub_dir: Promise { <pending> } }
my code:
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)
})
})
}
CodePudding user response:
The proposed structure is invalid as a directory can have one or more subdirectories -
{
dir: "foo",
sub_dir: { ... },
sub_dir: { ... }, // cannot reuse "sub_dir" key
}
Here's an alternative that will build a tree like this -
{
"test1":
{
"test2":
{
"test3":
{
"0001.dcm": true,
"0002.dcm": true,
"003.dcm": true
}
}
}
}
fs/promises and fs.Dirent
Here's an efficient, non-blocking program using Node's fast fs.Dirent objects and fs/promises module. This approach allows you to skip wasteful fs.exist
or fs.stat
calls on every path -
// 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 () {}
Now createTree
is simply a combination of tokenise
and parse
-
const createTree = (path = ".") =>
parse(tokenise(path))
createTree(".")
.then(r => console.log(JSON.stringify(r, null, 2)))
.catch(console.error)
Let's get some sample files so we can see it working -
$ 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
}
}
I hope you enjoyed reading this post. For added explanation and other ways to use async generators, see this Q&A.