1

I'm walking large directory tree recursively (from 100,000 to 1,000,000 objects) and need to add each file or directory to deeply nested object.

Let's assume I got file paths like

/path/to/file1
/path/to/file2
...
/pathX/file1000000

and I need to create following nested object based on them:

{
  "name": "/",
  "value": 300,
  "children": [
    { 
       "name": "/pathX",
       "value": 100,
       "children": [
       {
         "name": "/pathX/file1000000",
         "value": 100
       }
    },
    {
      "name": "/path",
      "value": 200,
      "children": [
        {
          "name": "/path/to",
          "value": 200,
          "children": [
            {
              "name": "/path/to/file1",
              "value": 100
            },

            {
              "name": "/path/to/file2",
              "value": 100
            }
          ]
        }
      ]
    }
  ]
}

The value is a file size or sum of nested file sizes. To keep things simple, let's assume its equal to 100 for file1, file2 and fileN.

I was able to build nested object for one file, but having issues with building it for many files with different paths:

const path = require('path')
const fs = require('fs')

let file = '/opt/bin/file1'
let size
fs.stat(file, (err, stats) => { size = stats.size })
let paths = file.split(path.sep)

let nameChild = file
let objChild = { "name" : nameChild, "value" : size }
let nameParent
let objParent

for (var i in paths) {

    if (i==0) continue

    nameParent = path.dirname(nameChild)

    objParent = { "name" : nameParent, "value" : size, "children" : [ objChild ] }

    nameChild = nameParent
    objChild = objParent

}

console.log(JSON.stringify(objParent))

1 Answer 1

2

There you go :)

function buildTree(pathes, getValueCB) {

  var currentPath, lastPath, node, parent, map = {
      "": {
        children: []
      }
    },
    stack = [""]

  for (let path of pathes) {
    let nodes = path.split("/");
    for (let i = 0; i < nodes.length; i++) {
      currentPath = "/" + nodes.slice(1, i + 1).join("/")
      lastPath = stack[stack.length - 1]
      parent = map[lastPath]
      if (!map[currentPath]) {
        node = {
          name: currentPath,
          value: getValueCB(currentPath),
          children: []
        }
        parent.children.push(node);
        map[currentPath] = node;
      }
      stack.push(currentPath)
    }
    stack = stack.slice(0, 1)
  }
  return map[""].children[0];
}

function getFileSizeSync() {
  return 200
}
var tree = buildTree(["/path/to/file1", "/path/to/file2"], function(path) {
  return getFileSizeSync(path)
})

console.log (tree)


Here's the updated version that calculates the size recursively. (I can't put it into a snippet, that's why i leave the old one)

var fs = require('fs')
var Path = require ('path')

function calcSize (node) {
    var children = node.children; 
    node.value = children.reduce (function (size, child) {
        return size + child.value || reduceSize (child);
    }, 0)
    return node.value;
}
function getFileSizeSync(path) {
  var size = fs.statSync(path).size
  return size
}

function buildTree(pathes, getValueCB) {

  var currentPath, lastPath, node, parent, map = {
      "": {
        children: []
      }
    },
    stack = [""]

  for (let path of pathes) {
    let nodes = path.split(Path.sep);
    for (let i = 0; i < nodes.length; i++) {
      currentPath = Path.sep + nodes.slice(1, i + 1).join(Path.sep)
      lastPath = stack[stack.length - 1]
      parent = map[lastPath]
      if (!map[currentPath]) {
        node = {
          name: currentPath,
          value: getFileSizeSync(currentPath),
          children: []
        }
        parent.children.push(node);
        map[currentPath] = node;
      }
      stack.push(currentPath)
    }
    stack = stack.slice(0, 1)
  }
  calcSize (map[""])
  return map[""].children[0];
}


var tree = buildTree(["/path/to/file1", "/path/to/file2"])

console.log (tree)
Sign up to request clarification or add additional context in comments.

3 Comments

I think you're missing the point that the parent directories should sum the file sizes within for their values
@Jamiec Indeed! Fixed it
@SystemsRebooter I added that part as well

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.