Generate a nested structure based on a list of file paths I'm currently working on a small application, as a learning exercise for a Javascript novice. I need to generate an object based on a folder structure. Here is an example of the folder structure:


  RootFolder/FolderA/FolderB/FileA
  
  RootFolder/FolderA/FolderB/FileB
  
  RootFolder/FolderA/FolderB/FolderC/FileA
  
  RootFolder/FolderA/FolderB/FolderC/FileB


The desired resulting object should have the following structure:

{
    RootFolder: {
        FolderA: {
            FolderB: {
                FileA: {},
                FileB: {},
                FolderC: {
                    FileA: {},
                    FileB: {}
                }
            }
        }
    }
};


So far I came up with the following code and it seems to be doing the job, but I'm concerned with 'eval' use and generally believe there is a more elegant way of doing it.



module.exports = {
  structure: function(structureArray) {
    var generatedObject = {};
    for (var i = 0; i &lt; structureArray.length; i++) {
      var objectElements = '';
      var path = (structureArray[i].split('/')).filter(Boolean);
      for (var l = 0; l &lt; path.length; l++) {
        if (objectElements.indexOf(path[l]) == -1 || path[l].length == 1) {
          objectElements += '["' + path[l] + '"]';
        }
        if (!(eval('generatedObject' + objectElements))) {
          eval('generatedObject' + objectElements + '= {}')
        }
      }
    }
    return generatedObject;
  }
};




structureArray contains full path strings as in the folder structure example above (e.g. 'RootFolder/FolderA/FolderB/FileA')
You can split each path at / using split and then use reduce() to build that object.



var paths = [
  'RootFolder/FolderA/FolderB/FileA',
  'RootFolder/FolderA/FolderB/FileB',
  'RootFolder/FolderA/FolderB/FolderC/FileA',
  'RootFolder/FolderA/FolderB/FolderC/FileB'
]

var obj = {}
paths.forEach(function(path) {
  path.split('/').reduce(function(r, e) {
    return r[e] || (r[e] = {})
  }, obj)
})

console.log(obj)




Here is how you can use this approach to read some directory and all of its nested content and create object from that. This approach is synchronous.

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

var p = path.resolve('C:\\your\\path\\here')
var result = {}

function buildObject(startPath) {
  var dir = fs.readdirSync(startPath)
  dir.forEach(function(e) {
    var newPath = path.join(startPath, e)

    var stat = fs.statSync(newPath);
    if (stat &amp;&amp; stat.isDirectory()) buildObject(newPath)
    if (stat.isFile()) {
      newPath.split('\\').reduce(function(r, a) {
        return r[a] || (r[a] = {})
      }, result)
    }
  })
}

buildObject(p)
console.log(result)