node.js 生成目录树文件

2023-09-24 15 0

说在前面

我们在很多地方都可以看到有这样的目录树结构,目录树可以很好的介绍项目中各文件目录的用途,帮助读者了解整个项目结构。
image.png
由于自己在项目中需要用到这个目录树来进行项目结构介绍,但是在网上简单的找了一下,没找到自己想要的工具,于是就自己动手用node撸了一个,输出效果如上图↑↑↑。

代码实现

依赖模块

需要使用fs和path模块。

const fs = require("fs");
const path = require("path");

参数配置

执行node命令的时候可以携带参数,具体参数如下:
执行node getFileTree.js -h 或 node getFileTree.js -help 控制台会打印提示信息。
node getFileTree.js [参数1] [参数2] [参数3] [参数4] [参数5]
具体代码如下:

let basepath = "../"; //解析目录路径
let filterFile = ["node_modules", "\\..*"]; //过滤文件名,使用,隔开
let stopFloor = 10; //遍历层数
let generatePath = "./fileTree.txt"; //生成文件路径
let isFullPath = true; //是否输出完整路径//获取入参
let args = process.argv.slice(2);
if (args[0] && (args[0] === "-h" || args[0] === "-help")) {console.log("node getFileTree.js [参数1] [参数2] [参数3] [参数4] [参数5]");console.log("参数说明");console.log("参数1:解析目录路径,默认为'../'");console.log("参数2:过滤文件名,使用','隔开,支持正则表达式,默认为'node_modules', '\\..*'");console.log("参数3:遍历文件最大层数,默认为10");console.log("参数4:生成文件路径,默认为'./fileTree.txt'");console.log("参数5:是否输出完整路径,默认为true");console.log("参数按顺序读取,不能省略,使用默认值需要输入' '占位,如下:");console.log("node getFileTree.js [参数1] ' ' [参数3] [参数4] [参数5]");process.exit();
}if (args[0] && args[0] !== " ") {basepath = args[0]; //解析目录路径
}
if (args[1] && args[1] !== " ") {filterFile = args[1].split(","); //过滤文件名,使用,隔开
}
if (args[2] && args[2] !== " ") {stopFloor = args[2]; //遍历层数
}
if (args[3] && args[3] !== " ") {generatePath = args[3]; //生成文件路径
}
if (args[4] && args[4] === "f") {isFullPath = false; //是否输出完整路径
}

目录输出以目标文件夹为起始路径

比如我们需要生产目录树的文件夹路径为’…/test’,我们并不希望输出目录树每一个目录都会带上’…/test’这一部分路径,所以应该将这一部分的路径删除。

function getPartPath(dirPath) {let base = basepath.split(/\/|\\/g);dirPath = dirPath.split(/\/|\\/g);while (base.length && dirPath.length && base[0] === dirPath[0]) {base.shift();dirPath.shift();}return dirPath.join("/");
}

过滤不想输出的目录文件

我们在打印目录树的时候也希望有些目录文件不被打印出来,如node_modules目录点开头的文件,程序默认的过滤规则为:let filterFile = ["node_modules", "\\..*"];

function isFilterPath(item) {for (let i = 0; i < filterFile.length; i++) {let reg = filterFile[i];if (item.match(reg) && item.match(reg)[0] === item) return true;}return false;
}

获取文件目录树

使用fs模块中的readdirSync获取目录下的文件目录列表;
使用fs模块中的statSync获取文件信息,isFile方法可以判断是文件还是目录。
是文件则将文件放进列表,是目录则需递归处理目录,最后输出目录树的json数据,具体代码如下:

function processDir(dirPath, dirTree = [], floor = 1) {if (floor > stopFloor) return;let list = fs.readdirSync(dirPath);list = list.filter((item) => {return !isFilterPath(item);});list.forEach((itemPath) => {const fullPath = path.join(dirPath, itemPath);const fileStat = fs.statSync(fullPath);const isFile = fileStat.isFile();const dir = {name: isFullPath ? getPartPath(fullPath) : itemPath,};if (!isFile) {dir.children = processDir(fullPath, [], floor + 1);}dirTree.push(dir);});return dirTree;
}

打印目录树

拼接目录树字符串。

function consoleTree(tree, floor = 1, str = "", adder = "───", isLast = false) {str += adder;for (let i = 0; i < tree.length; i++) {if (floor === 1 && i === 0) {fileTree += "\n" + "┌" + str + tree[i].name;} else if ((isLast || floor === 1) &&i === tree.length - 1 &&!tree[i].children) {fileTree += "\n" + "└" + str + tree[i].name;} else {fileTree += "\n" + "├" + str + tree[i].name;}if (tree[i].children)consoleTree(tree[i].children,floor + 1,str,adder,(isLast || floor === 1) && i === tree.length - 1);}
}

目录树输出到文件中

先清空再写入。

function writeTree(filePath, content) {clearTxt(generatePath);fs.writeFileSync(filePath, `${content}`);console.log(content);
}

清空文件数据

function clearTxt(filePath) {fileTree = "";fs.writeFileSync(filePath, "");
}

完整代码

/** @Author: zheng yong tao* @Date: 2022-03-16 21:27:07* @LastEditors: zheng yong tao* @LastEditTime: 2022-03-16 23:15:17* @Description:*/const fs = require("fs");
const path = require("path");let basepath = "../"; //解析目录路径
let filterFile = ["node_modules", "\\..*"]; //过滤文件名,使用,隔开
let stopFloor = 10; //遍历层数
let generatePath = "./fileTree.txt"; //生成文件路径
let isFullPath = true; //是否输出完整路径//获取入参
let args = process.argv.slice(2);
if (args[0] && (args[0] === "-h" || args[0] === "-help")) {console.log("node getFileTree.js [参数1] [参数2] [参数3] [参数4] [参数5]");console.log("参数说明");console.log("参数1:解析目录路径,默认为'../'");console.log("参数2:过滤文件名,使用','隔开,支持正则表达式,默认为'node_modules', '\\..*'");console.log("参数3:遍历文件最大层数,默认为10");console.log("参数4:生成文件路径,默认为'./fileTree.txt'");console.log("参数5:是否输出完整路径,默认为true");console.log("参数按顺序读取,不能省略,使用默认值需要输入' '占位,如下:");console.log("node getFileTree.js [参数1] ' ' [参数3] [参数4] [参数5]");process.exit();
}if (args[0] && args[0] !== " ") {basepath = args[0]; //解析目录路径
}
if (args[1] && args[1] !== " ") {filterFile = args[1].split(","); //过滤文件名,使用,隔开
}
if (args[2] && args[2] !== " ") {stopFloor = args[2]; //遍历层数
}
if (args[3] && args[3] !== " ") {generatePath = args[3]; //生成文件路径
}
if (args[4] && args[4] === "f") {isFullPath = false; //是否输出完整路径
}function getPartPath(dirPath) {let base = basepath.split(/\/|\\/g);dirPath = dirPath.split(/\/|\\/g);while (base.length && dirPath.length && base[0] === dirPath[0]) {base.shift();dirPath.shift();}return dirPath.join("/");
}function isFilterPath(item) {for (let i = 0; i < filterFile.length; i++) {let reg = filterFile[i];if (item.match(reg) && item.match(reg)[0] === item) return true;}return false;
}function processDir(dirPath, dirTree = [], floor = 1) {if (floor > stopFloor) return;let list = fs.readdirSync(dirPath);list = list.filter((item) => {return !isFilterPath(item);});list.forEach((itemPath) => {const fullPath = path.join(dirPath, itemPath);const fileStat = fs.statSync(fullPath);const isFile = fileStat.isFile();const dir = {name: isFullPath ? getPartPath(fullPath) : itemPath,};if (!isFile) {dir.children = processDir(fullPath, [], floor + 1);}dirTree.push(dir);});return dirTree;
}console.log("获取中,请稍后……");
let dirTree = [];
dirTree = processDir(basepath, dirTree);
let fileTree = '';function consoleTree(tree, floor = 1, str = "", adder = "───", isLast = false) {str += adder;for (let i = 0; i < tree.length; i++) {if (floor === 1 && i === 0) {fileTree += "\n" + "┌" + str + tree[i].name;} else if ((isLast || floor === 1) &&i === tree.length - 1 &&!tree[i].children) {fileTree += "\n" + "└" + str + tree[i].name;} else {fileTree += "\n" + "├" + str + tree[i].name;}if (tree[i].children)consoleTree(tree[i].children,floor + 1,str,adder,(isLast || floor === 1) && i === tree.length - 1);}
}
console.log("生成中,请稍后……");
function writeTree(filePath, content) {clearTxt(generatePath);fs.writeFileSync(filePath, `${content}`);console.log(content);
}
function clearTxt(filePath) {fileTree = "";fs.writeFileSync(filePath, "");
}
consoleTree(dirTree);
writeTree(generatePath,fileTree);
console.log("生成结束");

代码地址

Gitee:https://gitee.com/zheng_yongtao/node-scripting-tool.git

image.png
csdn资源下载:https://download.csdn.net/download/Twinkle_sone/84994970

代码编程
赞赏

相关文章

Google以21亿美元的价格收购了健康追踪器Fitbit
增长模型拆解:分享有礼裂变玩法的底层逻辑与细节设计
怎么做好B端数据运营?
基于两个实际案例,分享自己2020年运营的一些心得
数字化营销时代:企业如何从“推时代”进阶“拉时代”
谷歌三星杀进来了,高通为啥一点不怕?