读取文件夹树并将树转换为对象

时间:2013-09-21 10:33:24

标签: node.js recursion fs

我有以下文件夹结构:

+---controllers
|   |   index.js
|   |   
|   +---api
|   |       index.js
|   |       test.js
|   |       
|   \---routes
|       |   index.js
|       |   
|       \---partials
|           |   index.js
|           |   
|           +---bugs
|           +---compatibility
|           +---documentation
|           |       amd.js
|           |       api.js
|           |       jquery.js
|           |       options.js
|           |       usage.js
|           |       
|           \---installation

我正在尝试从树中创建一个看起来像这样的对象:

{
    api: {
        index: require("index.js"),
        test: require("test.js")
    },
    routes: {
        index: require("index.js"),
        partials: {
            index: require("index.js"),
            bugs: {},
            compatibility: {},
            documentation: {
                amd: require("amd.js"),
                api: require("api.js"),
                jquery: require("jquery.js"),
                options: require("options.js"),
                usage: require("usage.js")
            },
            installation: {}
        }
    }
}

我只是无法弄清楚这样做的逻辑,我设法只使用以下代码获取树的数组:

/**
 * Controllers
 */

var path = require("path"),
    util = require("util"),
    fs = require("fs"),
    wrench = require("wrench");

var controllers = {},
    tree = wrench.readdirSyncRecursive(path.resolve(__dirname, "./")).filter(function (value) {
        return value !== "index.js";
    });


var key,
    i = tree.length - 1;

while (i >= 0) {

    key = tree[i];

    console.log(fs.lstatSync(path.resolve(__dirname, key)).isDirectory(), key.split(path.sep));

    i--;
}

module.exports = controllers;

在开始循环文件夹树之后,我不确定我应该如何创建对象,但是我想我只能在有一些递归函数的情况下才能创建它?

修改

我之所以这样做,是因为我正试图为我的快速应用程序提供某种动态路由。

在我的快递申请中,我会有类似的内容:

application.get("/api/index", controllers.api.index);
application.get("/api/test", controllers.api.test);
application.get("/", controllers.routes.index);
application.get("/partials/", controllers.routes.partials.index);
application.get("/partials/documentation/amd", controllers.routes.partials.documentation.amd);

...

每个文件都会导出类似于:

的内容
exports.index = function (request, response) {
    return response.render("index");
};

取决于文件的位置以及可能具有更多逻辑(如果有必须加载的模型)。

所以可能有一种更好的方式来管理动态路线而不是我正在尝试的,如果是这样的话,我会开始寻求建议。

2 个答案:

答案 0 :(得分:3)

我为你的案例想出了一个递归文件助行器。

var fs = require('fs');
var filetree = {};

var walkDirectory = function(path, obj) {
  var dir = fs.readdirSync(path);
  for (var i = 0; i < dir.length; i++) {
    var name = dir[i];
    var target = path + '/' + name;

    var stats = fs.statSync(target);
    if (stats.isFile()) {
      if (name.slice(-3) === '.js') {
        obj[name.slice(0, -3)] = require(target);
      }
    } else if (stats.isDirectory()) {
      obj[name] = {};
      walkDirectory(target, obj[name]);
    }
  }
};

walkDirectory('./controllers', filetree);
console.log(filetree);

该函数将扫描目录,如果该文件是脚本,则将加载该文件。如果它是一个目录,该函数会将目录引用传递给它自己并再次执行相同的操作。

答案 1 :(得分:0)

您可以使用以下模块来帮助自己:

npm dree

有很多自定义选项,结果可能是这样的:

{
  "name": "sample",
  "path": "D:/Github/dree/test/sample",
  "relativePath": ".",
  "type": "directory",
  "size": "1.79 MB",
  "children": [
    {
      "name": "backend",
      "path": "D:/Github/dree/test/sample/backend",
      "relativePath": "backend",
      "type": "directory",
      "size": "1.79 MB",
      "children": [
        {
          "name": "firebase.json",
          "path": "D:/Github/dree/test/sample/backend/firebase.json",
          "relativePath": "backend/firebase.json",
          "type": "file",
          "extension": "json",
          "size": "29 B"
        }, 
        {
          "name": "server",
          "path": "D:/Github/dree/test/sample/backend/server",
          "relativePath": "backend/server",
          "type": "directory",
          "size": "1.79 MB",
          "children": [
            {
              "name": "server.ts",
              "path": "D:/Github/dree/test/sample/backend/server/server.ts",
              "relativePath": "backend/server/server.ts",
              "type": "file",
              "extension": "ts",
              "size": "1.79 MB"
            }
          ]
        }
      ]
    }
  ]
}

甚至可以返回一个字符串,如下所示:

sample
 └─> backend
     ├── firebase.json
     ├── hello.txt
     └─> server
         └── server.ts

您可以使用扩展名选项使用它来获取仅包含javascript文件的结构。然后,您只需要将获得的结构转换为所需的结构即可。

此codeandbox具有解决方案(请参阅solution.js文件):

Edit Setup Basic Node.js Server

您还可以使用dree的文件和目录回调,这是另一个codeandbox(请参阅solution.js文件):

Edit Setup Basic Node.js Server