封装一个快速生成目录树的全局脚本

简介: 封装一个快速生成目录树的全局脚本

说在前面

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

思路分析

首先我们需要先明确一下我们这个工具需要实现的功能:

  • 1、可以生成指定目录的文件树文件
  • 2、可以方便地在任意目录下生成

那么我们需要做的也就是以下两步:

  • 1、编写一个可以生成指定目录文件树的文件
  • 2、将脚本封装成全局脚本

为了方便插件的使用、提高用户体验,我们可以使用命令行交互的方式来获取所需参数。

功能实现

一、使用命令行交互来获取所需参数

编写脚本之前我们需要先明确一下需要的参数

  • 1、需要生成文件树的根目录路径;
  • 2、生成过程中需要忽略的文件或目录;
  • 3、生成文件树的深度;
  • 4、生成的文件树文件存放路径;

这里使用到了我自己之前基于inquirer进行二次封装的@jyeontu/j-inquirer,与inquirer相比,@jyeontu/j-inquirer增加了文件夹选择器的交互方式,我们可以直接使用其来选择需要生产目录树的文件目录和生成文件存放的位置。

@jyeontu/j-inquirer这个工具的具体使用手册可以看这里:https://gitee.com/zheng_yongtao/node-scripting-tool/tree/master/src/JInquirer

const JInquirer = require("@jyeontu/j-inquirer");
const fs = require("fs");
const path = require("path");
async init() {
    const options = this.getOptions();
    let j = new JInquirer(options);
    let res = await j.prompt();
    this.config = res;
    this.generateTree(res);
}
getOptions() {
    const basePath = this.config.basePath || __dirname;
    return [
      {
        type: "folder",
        message: "请选择文件夹:",
        name: "basepath",
        default: "",
        pathType: "absolute",
        dirname: basePath,
      },
      {
        type: "input",
        message: "请输入需要过滤的文件名(英文逗号隔开):",
        name: "filterFile",
        notNull: false,
      },
      {
        type: "input",
        message: "请输入需要遍历的层数:",
        name: "stopFloor",
        notNull: false,
      },
      {
        type: "folder",
        message: "请选择生成文件存放位置:",
        name: "generatePath",
        default: "",
        pathType: "absolute",
        dirname: basePath,
      },
    ];
  }

获取到我们需要的参数之后我们便可以开始编写生成文件目录树的代码了:

二、编写目录文件树生成逻辑

  • 1、递归获取文件目录

递归结束条件为传入参数的最大遍历深度:if (floor > stopFloor) return;

通过readdirSync可以获取指定目录下的所有文件列表,通过statSync方法获取文件属性,再通过isFile方法判断是文件还是目录,如果当前遍历到的为目录,则需要递归遍历该目录下的所有文件……

processDir(dirPath, dirTree = [], floor = 1) {
    const { stopFloor } = this.config;
    if (floor > stopFloor) return;
    let list = fs.readdirSync(dirPath);
    list = list.filter((item) => {
      return !this.isFilterPath(item);
    });
    list.forEach((itemPath) => {
      const fullPath = path.join(dirPath, itemPath);
      const fileStat = fs.statSync(fullPath);
      const isFile = fileStat.isFile();
      const dir = {
        name: itemPath,
      };
      if (!isFile) {
        dir.children = this.processDir(fullPath, [], floor + 1);
      }
      dirTree.push(dir);
    });
    return dirTree;
  }
  • 2、过滤不需要的文件

有时候我们不希望打印出某些文件目录(如:node_modules),我们在输入配置的时候可以进行设置,遍历文件目录的过程中会过滤掉相关的文件。

isFilterPath(item) {
  let { filterFile } = this.config;
  filterFile = filterFile.split(",");
  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;
}
  • 3、将文件树列表转换为字符串

前面我们生成的文件树是以列表的形式保存,现在我们需要将其转换成使用制表符连接的字符串的格式。

consoleTree(tree, floor = 1, str = "", adder = "───", isLast = false) {
  str += adder;
  for (let i = 0; i < tree.length; i++) {
    if (floor === 1 && i === 0) {
      this.fileTree += "\n" + "┌" + str + tree[i].name;
    } else if (
      (isLast || floor === 1) &&
      i === tree.length - 1 &&
      !tree[i].children
    ) {
      this.fileTree += "\n" + "└" + str + tree[i].name;
    } else {
      this.fileTree += "\n" + "├" + str + tree[i].name;
    }
    if (tree[i].children)
      this.consoleTree(
        tree[i].children,
        floor + 1,
        str,
        adder,
        (isLast || floor === 1) && i === tree.length - 1
      );
  }
}
  • 4、将生成的目录树写入 txt 文件

前面我们已经生成了字符串格式的目录树,所以我们可以直接将生成的字符串写入 txt 文件即可,注意写入前我们需要先将原有内容情况。

writeTree(filePath, content) {
  this.clearTxt(filePath);
  fs.writeFileSync(filePath, `${content}`);
}
clearTxt(filePath) {
  this.fileTree = "";
  fs.writeFileSync(filePath, "");
}

三、封装成全局插件

  • 1、准备一个脚本文件

创建一个文件 bin.js 作为启动脚本。

#!/usr/bin/env node
const path = require("path");
const GetFileTree = require("./GetFileTree.js");
const basePath = process.argv[2] || path.join(process.argv[1], "../");
console.log(process.argv, basePath);
const gft = new GetFileTree({ basePath });
gft.init();
  • 2、package.json 中配置启动命令

package.json文件中配置脚本启动命令,需要设置 bin 属性,这个配置帮助我们将包内的可执行脚本文件注入系统环境。多个命令时,支持对象配置命令:

{
  "name": "mt-cli",
  "version": "1.0.1",
  "bin": {
    "getFileTree": "./bin.js"
  }
}
  • 3、上传到 npm

登录自己的 npm 账号后可以使用命令将该包上传到 npm 仓库。

npm publish

四、插件安装使用

  • 1、插件安装
npm i -g getFileTree
  • 2、插件使用

全局安装后我们就可以在任意目录下使用getFileTree 目录绝对路径命令来生成文件目录树,如下:

getFileTree E:\myGitee\md文件夹

然后按照提示选择或输入相关的参数即可,生成的文件如下:

源码地址

https://gitee.com/zheng_yongtao/node-scripting-tool/tree/master/src/getFileTree

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,在此谢谢大家的支持,我们下文再见 🙌。

目录
相关文章
|
6月前
|
编译器 C# 开发者
C# 10.0中的全局`using`指令:简化命名空间引用的新方式
【1月更文挑战第4天】本文介绍了C# 10.0中引入的全局`using`指令,该指令允许开发者在项目级别统一管理命名空间引用,从而消除源文件中重复的`using`语句。全局`using`指令通过减少冗余代码、提高可维护性和统一命名空间管理,为开发者带来了更高效的编码体验。文章详细解释了如何实现全局`using`指令,并探讨了其在实际项目中的优势和适用场景。
|
22天前
实现文件目录结构功能
实现文件目录结构功能
11 1
|
6月前
|
JavaScript 前端开发
详解单文件组件
详解单文件组件
|
6月前
|
定位技术 Python
Python依据某一文件夹中大量文件的名称复制另一文件夹中的同名文件
Python依据某一文件夹中大量文件的名称复制另一文件夹中的同名文件
|
11月前
|
前端开发 小程序 PHP
laravel5.8(四)引入自定义常量文件及公共函数文件
开发过程中,我们一般会用到一些不会改变,或者改变不是很频繁的值,这样的值我们一般将他们定义成常量。 比如网站根目录,或者分页数,或者域名等等。 那我们如何在laravel5.8中引入自定义的常量文件及公共的函数文件呢。 大概有两种方式: 1:框架目录下引入(不推荐) 在框架目录vendor下新建常量文件const.php,以及公共函数文件function.php 在autoload.php文件中引入。 这种方法是可以的,但是不推荐,框架目录下最好都是框架自己的那些文件,正常来说,框架的文件我们在开发过程中,git是不会进行托管的。 2:在app目录下引入 在bootstrap目录下新建常量文件
69 0
导出项目目录树结构
在cmd中切换到自己所需要导出项目树结构的根目录下,在win中可以使用cd来切换文件夹
157 0
|
JavaScript 前端开发
脚本可放置与外部文件中
脚本可放置与外部文件中
62 1
定义一个事件需要单独新建一个文件吗?底层原理是什么?
定义一个事件需要单独新建一个文件吗?底层原理是什么?
|
文件存储
Yii2.0框架提供了内置的文件访问组件,可以通过配置只允许访问指定的目录,防止非法文件的包含。这个如何使用?
Yii2.0框架提供了内置的文件访问组件,可以通过配置只允许访问指定的目录,防止非法文件的包含。这个如何使用?
146 0
|
PHP 开发者
嵌套文件包含路径问题|学习笔记
快速学习嵌套文件包含路径问题
嵌套文件包含路径问题|学习笔记