Node.js折腾记一(改进):文件夹目录树获取

栏目: Node.js · 发布时间: 5年前

内容简介:源码可以戳这里:

这是第一个版本:

  1. 用来干什么:想干嘛干嘛
  2. 为什么写:写来玩,学习 node.js 文件系统相关api;树结构这种东西还是挺不错的,会用会造才是真的会
  3. 用了什么: fs.readdir(dir) , fs.stat(dir).isFile() , path 处理路径等
  4. 思路:
    • 读取当前文件夹(不是文件夹的另作处理),获得其下所有文件和目录组成的数组;
    • 循环该数组,判断是文件夹还是文件,文件的话直接push到 childFiles (对象有两个属性: short 文件名, full 完整文件路径)
    • 文件夹的话,先把当前文件夹作为 key ,存到父级文件夹的 childDir 属性下,然后自调用传当前文件夹路径
    • 每一层文件夹都包含三个属性: dir 文件夹路径, childFiles 子文件, childDir 子文件夹,存储为对象结构
    • 以上步骤重复,直到达到最底层空文件夹或该文件夹只有文件

改进:

  • 添加目录过滤规则(正则表达式);根据正则表达式,过滤(i)或只获取(c); 默认过滤 ["/node_modules|.git/i"]
  • 过滤的正则表达式格式: ["regx"] ,如 ["/node_modules|.git/i"]["/components/"]
  • 添加结构树输出,类似 treetreer ,类似在掘金到处可见的项目结构那种
  • 通过 npm scripts 使用不同的命令,添加不同的参数, process.env 传递变量(过滤类型 i/c ,正则)

源码可以戳这里: github地址

一、输出的内容

  • components-dir-tree.json

{
    "dir": "D:\\node-test\\components",
    "childFiles": [
        {
            "short": "components-dir-tree.json",
            "full": "D:\\node-test\\components\\components-dir-tree.json"
        },
        {
            "short": "file.js",
            "full": "D:\\node-test\\components\\file.js"
        },
        {
            "short": "index.js",
            "full": "D:\\node-test\\components\\index.js"
        }
    ],
    "childDir": {
        "no": null,
        "test": {
            "dir": "D:\\node-test\\components\\test",
            "childFiles": [],
            "childDir": {
                "aa": {
                    "dir": "D:\\node-test\\components\\test\\aa",
                    "childFiles": [
                        {
                            "short": "bb.js",
                            "full": "D:\\node-test\\components\\test\\aa\\bb.js"
                        }
                    ],
                    "childDir": {
                        "cc": null
                    }
                }
            }
        }
    }
}
复制代码
  • components-dir-tree.json: output

"output": "D:\\node-test\n└─ components\n    ├─ components-dir-tree1.json\n    ├─ file.2.js\n    ├─ file.bakeup.js\n    ├─ file.js\n    ├─ index.js\n    ├─ log.js\n    ├─ node-test-dir-tree.json\n    ├─ run-sh.js\n    ├─ test\n      └─ aa\n        ├─ bb.js\n        └─ cc\n    └─ timeFormat.js\n"
复制代码
D:\node-test
├─ components
    ├─ components-dir-tree1.json
    ├─ file.2.js
    ├─ file.bakeup.js
    ├─ file.js
    ├─ index.js
    ├─ log.js
    ├─ node-test-dir-tree.json
    ├─ run-sh.js
    ├─ test
      └─ aa
        ├─ bb.js
        └─ cc
    └─ timeFormat.js
├─ index.js
├─ json
    ├─ a.json
    └─ b.json
├─ package-lock.json
├─ package.json
├─ README.md
├─ scripts
    └─ generateComponent.js
└─ sh
    └─ sh1.js
复制代码
Node.js折腾记一(改进):文件夹目录树获取

二、主函数 getDirTree

//components/file.2.js:
const fs = require('fs');
// 获取获取目录的类型,过滤i: ignore/包含c: contain
const type = process.env.getDirTreeType;
// 正则表达式 ["/node_modules|.git/i"]
let reg = process.env.getDirTreeReg;

// 正则表达式转换
let modifier = reg.substring(reg.lastIndexOf('/')+1, reg.lastIndexOf(']')) || 'i'; // 修饰符
reg = reg.substring(reg.indexOf('/')+1, reg.lastIndexOf('/')); // 截取表达式模型

reg = new RegExp(reg, modifier); // 生成正则表达式

let firstRun = true; // getDirTree首次执行
let output = ''; // 生成目录结构字符串
/**
 * 获取目录下的文件树
 * @param {读取的路径} dir 
 * @returns 返回 dir目录下的文件树
 */
function getDirTree(dir) {
  let obj = {
    dir: dir,
    childFiles: [],
    childDir: {}
  };
  let objStr = JSON.stringify(obj);
  if (firstRun && isFile(dir)) return console.log(`${dir}: 不是文件夹`.redBG);

  let files = readDir(dir);
  
  if (firstRun) {
    output=`${dir}\n`;
    // 根据正则过滤文件、文件夹
    files = filesFilter(files);
    // 过滤之后的文件、文件夹列表
    log('files: ', files);
  }

  firstRun = false;

  // 遍历文件
  files.forEach((file, index) => {
    let tempdir = `${dir}\\${file}`;
    let dirname = getDirName(tempdir);
    // dir深度
    let dirDeep = new Array(tempdir.split('\\').length - 2).fill(0);
    
    dirDeep = dirDeep.reduce((acc,cur) => 
      acc = (dirDeep.length > 1 ? '  ' : '') + acc, 
      index === files.length - 1 ? '└─ ' : '├─ '
    );
    
    output += `${dirDeep}${dirname}\n`;
    obj.output = output;

    log('output: \n'.green, output);

    if (isFile(tempdir)) {
      obj.childFiles.push({
        short: file, // 文件名
        full: tempdir // 完整路径
      });
      
    } else {
      // console.log('tempdir: ',tempdir);
      
      // 在当前文件夹的对象下 childDir 属性(1),以文件夹名作为key(2),
      // (2)的值是该目录下 路径dir、childFiles子文件、childDir子文件夹组成的对象或null
      obj.childDir[dirname] = getDirTree(tempdir);
    }
  });
  return JSON.stringify(obj) === objStr ? null : obj;
}
复制代码

三、 工具 函数

  • 目录过滤:

// 根据正则过滤文件、文件夹
function filesFilter(files) {
  switch (type) {
    case 'i': // 过滤掉忽略的文件、文件夹
      files = files.filter(item => !reg.test(item));
      break;
    case 'c': // 包含
      files = files.filter(item => reg.test(item));
      break;
    default:
      break;
  }
  return files;
}

复制代码
  • 其他 readDir / isFile / getDirName

// 读取路径下的文件、文件夹
function readDir(dir) {
  return fs.readdirSync(dir, (err, files) => {
    if (err) throw err;
    // console.log(`${dir}, files: `.green, files);
    // if (!files.length) console.log(`${dir}: 文件夹为空`.redBG);
    return files;
  })
}

// 判断制定路径是否是文件
function isFile(dir) {
  return fs.statSync(dir).isFile();
}

// 获取目录名
function getDirName(dir) {
  let tempdir = dir.substr(dir.lastIndexOf('\\')+1, dir.length);
  return tempdir;
}

// const components_out = readFile(path.resolve(__dirname, './components-dir-tree.json'));
// console.log('components-dir-tree: ', components_out);

// 读取指定目录的文件
function readFile(dir) {
  let result = fs.readFileSync(dir, 'utf-8');
  return (
    result 
    ? {
      dir: dir,
      result: result
    } 
    : null
  );
}

module.exports = {
  getDirTree,
  readDir,
  isFile,
  readFile
}
复制代码

四、调用

  • package.json:

{
  ...
  "scripts": {
    "gettreer": "node index.js --i",
    "gettreer:i": "node index.js --i",
    "gettreer:c": "node index.js --c",
  },
  ...
}
复制代码
  • 函数主体

// components/index.js
// 获取目录树初始化
function getDirTreeInit() {
  program
    .version('0.0.1')
    .option('-i --i [i]', 'ignore file or files')
    .option('-c --c [c]', 'contain file or files')
    .parse(process.argv);
  
  // 接受命令行参数 npm run gettreer:i ["/node_modules|.git/i"]
  let reg = (typeof program.i === 'string' && program.i) 
    || (typeof program.c === 'string' && program.c)  
    || '[/node_modules|.git/i]';
  process.env.getDirTreeType = program.c ? 'c' : 'i'; // 忽略过滤ignore
  process.env.getDirTreeReg = reg; // 正则表达式

  const { getDirTree, getDirName } = '' 
    ? require('./file.js') // 上个版本
    : require('./file.2.js'); // 本次改进版本

  let treeObj = getDirTree(componentDir);
  // console.log('treeObj: ',treeObj);

  if (treeObj) {
    let outdir = `${__dirname}\\${getDirName(componentDir)}-dir-tree.json`;

    // 写入文件
    fs.writeFile(outdir, JSON.stringify(treeObj, '', '\t'), 'utf8', (err) => {
      if (err) throw err;
      console.log(`目录树已输出为文件保存: ${outdir}`.greenBG);
    });
  }
}
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数据分析技术白皮书

数据分析技术白皮书

伍海凤、刘鹏、杨佳静、马师慧Sara、李博、Shirley Song、Zinc、李晓艳 / 2016-8-11 / 0

关于数据分析技术白皮书(Analytics Book 中文版),主要内容围绕: 1. 分析(Analytics):网站分析 & APP分析 2. 谷歌分析工具的原理、部署与使用 3. 开源网站分析工具的原理、部署与使用 4. Log日志分析原理 5. 网站分析的维度与指标定义 6. 如何炼成为一个互联网数据分析师 请访问书的数据分析技术白皮书官网“免费”阅......一起来看看 《数据分析技术白皮书》 这本书的介绍吧!

html转js在线工具
html转js在线工具

html转js在线工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具