Files
tree-generator/Releases/v1.0.0/source/tree_architecture_design.md
2026-05-16 17:34:32 +08:00

11 KiB
Raw Blame History

目录树生成脚本 - 架构设计文档

项目 ID: PROJ-20260509011 | 任务 ID: T023 | 功能清单: F013-F020 设计者: 脚本架构师 | 日期: 2026-05-16 | 状态: 待审批


1. 项目结构

项目根目录/
├── tree.sh                    # 主脚本(单文件,约 300-400 行)
├── .treeignore                # 忽略配置文件(可选,用户创建)
├── tree_output.md             # 默认输出文件(脚本生成)
└── README.md                  # 使用文档(后续任务产出)

设计原则:单文件脚本,零安装依赖,即拿即用。


2. 模块说明

2.1 parse_args

  • 负责功能: F013 路径输入解析
  • 输入: 命令行参数
  • 输出: 规范化路径变量 TARGET_PATH
  • 依赖: bash 内置 getopts

2.2 load_ignore_config

  • 负责功能: F014 加载忽略配置
  • 输入: .treeignore 文件路径
  • 输出: 忽略模式数组 IGNORE_PATTERNS[]
  • 依赖: bash 内置 read/while

2.3 should_ignore

  • 负责功能: F014 忽略判断
  • 输入: 目录名 + IGNORE_PATTERNS[]
  • 输出: 布尔值0=不忽略, 1=忽略)
  • 依赖: bash 内置 case/模式匹配

2.4 traverse_directory

  • 负责功能: F015 递归遍历
  • 输入: 路径 + 忽略列表 + 缩进级别
  • 输出: 目录树结构(嵌套关联数组)
  • 依赖: bash 内置 for/find

2.5 render_tree

  • 负责功能: F016 目录树渲染
  • 输入: 目录树结构
  • 输出: 格式化字符串(├──/└──)
  • 依赖: bash 内置字符串操作

2.6 collect_files

  • 负责功能: F017 文件收集
  • 输入: 路径 + 忽略列表
  • 输出: 文件路径列表(数组)
  • 依赖: bash 内置 find

2.7 render_file_list

  • 负责功能: F017 文件树渲染
  • 输入: 文件路径列表
  • 输出: 格式化字符串(带完整路径)
  • 依赖: bash 内置字符串操作

2.8 output_terminal

  • 负责功能: F018 终端输出
  • 输入: 格式化字符串
  • 输出: 终端显示
  • 依赖: bash 内置 echo/printf

2.9 save_markdown

  • 负责功能: F019 Markdown 保存
  • 输入: 格式化字符串 + 输出路径
  • 输出: tree_output.md 文件
  • 依赖: bash 内置重定向

2.10 compute_stats

  • 负责功能: F020 统计信息
  • 输入: 遍历结果
  • 输出: 目录数、文件数、总大小
  • 依赖: du/find/wc

3. 技术选型

3.1 语言与运行时

  • Bash 4.0+ — 支持关联数组,现代 Linux 发行版标配(已确认)
  • find (POSIX) — 递归遍历目录,支持 -name/-prune 过滤(已确认)
  • du (POSIX) — 计算目录总大小(已确认)
  • stat / ls (POSIX) — 获取文件大小,跨平台兼容(已确认)
  • wc (POSIX) — 统计行数/条目数(已确认)

3.2 第三方库

本项目不引入任何第三方库。全部使用 POSIX/Bash 内置工具,确保:

  • 零安装依赖,开箱即用
  • 兼容所有主流 Linux 发行版Ubuntu/CentOS/Debian/Arch 等)
  • 兼容 macOSBash 5.x / zsh 兼容模式)

4. 功能详细设计

4.1 F013 - 路径输入解析

用法:

./tree.sh [路径] [选项]

选项:

  • -p, --path <路径> — 指定目标目录(支持相对/绝对路径)
  • -o, --output <文件> — 指定输出文件路径(默认 tree_output.md
  • -d, --depth <N> — 限制递归深度(默认无限制)
  • -f, --files — 同时生成文件树
  • -s, --no-stats — 不显示统计信息
  • -h, --help — 显示帮助信息
  • -v, --version — 显示版本信息

路径规范化:相对路径自动转换为绝对路径,使用 cd + pwd 组合实现。

4.2 F014 - 忽略配置

配置方案:支持两级忽略配置

  • 内置默认忽略列表(低优先级)— 硬编码在脚本中
  • .treeignore 文件(高优先级)— 每行一个模式(支持 glob

内置默认忽略:

  • .git .svn .hg — 版本控制
  • node_modules vendor bower_components — 包管理
  • pycache *.pyc .pytest_cache — Python
  • .DS_Store Thumbs.db — 系统文件
  • .idea .vscode .settings — IDE
  • dist build out target — 构建产物
  • .next .nuxt .output — 框架产物

.treeignore 文件格式:

# 注释行(以 # 开头)
vendor/
*.log
temp/

4.3 F015 - 递归遍历目录

数据结构:使用 bash 关联数组存储树结构

declare -A TREE_NODES    # 键=节点ID, 值="name|type|parent_id"
declare -A TREE_CHILDREN # 键=父节点ID, 值=子节点ID列表空格分隔

遍历算法:对目录中每个条目,先检查是否应忽略,再判断是目录还是文件。目录则递归深入(受深度限制),文件则直接加入节点。

4.4 F016 - 目录树渲染

输出格式规范:

.
├── src/
│   ├── main.sh
│   ├── utils/
│   │   ├── helpers.sh
│   │   └── logger.sh
│   └── config.sh
├── tests/
│   └── test_main.sh
├── .treeignore
└── README.md

渲染规则:

  • 根节点显示为 .
  • 中间节点前缀:├──
  • 最后一个节点前缀:└──
  • 目录名后缀 /
  • 缩进单位:(竖线 + 3空格或 4空格用于最后一项之后

4.5 F017 - 文件树

输出格式:

文件列表(共 N 个文件):
./src/main.sh
./src/utils/helpers.sh
./src/utils/logger.sh
./src/config.sh
./tests/test_main.sh
.treeignore
README.md

4.6 F018 - 终端输出

  • 使用 printf 替代 echo 确保跨平台一致性
  • 支持彩色输出(可选,检测终端是否支持)
  • 统计信息以分隔线包围,醒目展示

4.7 F019 - Markdown 保存

输出文件:tree_output.md(默认)

Markdown 格式包含:

  • 标题:目录树 - 目标路径
  • 生成时间戳
  • 目录结构(代码块包裹)
  • 文件列表(有序列表)
  • 统计信息

4.8 F020 - 统计信息

统计项:

  • 目录数 — 遍历过程中计数(排除忽略目录)
  • 文件数 — 遍历过程中计数(排除忽略文件)
  • 总大小 — du -sb 获取字节数,转换为人类可读格式

输出格式:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  统计信息
  目录数12
  文件数45
  总大小2.3 MB
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

5. 错误处理策略

5.1 错误分类与处理

  • 路径不存在(错误码 1— 输出错误信息到 stderrexit 1
  • 无读取权限(错误码 2— 输出错误信息到 stderrexit 2
  • 路径不是目录(错误码 3— 输出错误信息到 stderrexit 3
  • 输出目录不可写(错误码 4— 输出错误信息到 stderrexit 4
  • 深度参数无效(错误码 5— 输出错误信息到 stderrexit 5
  • 权限不足子目录(非致命)— 跳过并警告
  • 符号链接循环(非致命)— 检测并跳过,警告输出

5.2 安全机制

  • set -euo pipefail — 遇到错误退出、未定义变量报错、管道错误传播
  • 符号链接循环检测 — inode 去重
  • trap cleanup EXIT — 脚本退出时清理临时资源

5.3 警告 vs 错误

  • 致命错误exit路径不存在、无权限读取根目录、参数无效
  • 可恢复错误warn子目录无权限、符号链接循环、单个文件读取失败
  • 所有警告输出到 stderr不污染 stdout

6. 接口定义

6.1 模块间数据流

parse_args → TARGET_PATH, OUTPUT_FILE, MAX_DEPTH, SHOW_FILES
       ↓
load_ignore_config → IGNORE_PATTERNS[]
       ↓
traverse_directory + should_ignore → TREE_NODES, TREE_CHILDREN
       ↓
render_tree (F016) + render_file_list (F017) → 格式化字符串
       ↓
  ┌───────────────────┬────────────────────┐
  ↓                   ↓                    ↓
output_terminal   save_markdown      compute_stats
  (F018)            (F019)             (F020)
  ↓                   ↓                    ↓
终端显示          tree_output.md    统计信息追加

6.2 全局变量定义

TARGET_PATH=""                    # 目标目录路径(绝对路径)
OUTPUT_FILE="tree_output.md"      # 输出文件路径
MAX_DEPTH=""                      # 最大递归深度(空=无限制)
SHOW_FILES=false                  # 是否生成文件树
SHOW_STATS=true                   # 是否显示统计信息
IGNORE_PATTERNS=()                # 忽略模式数组
declare -A TREE_NODES             # 节点存储
declare -A TREE_CHILDREN          # 子节点关系
NODE_COUNTER=0                    # 节点计数器
DIR_COUNT=0                       # 目录计数
FILE_COUNT=0                      # 文件计数
TOTAL_SIZE=0                      # 总大小(字节)

6.3 函数签名

  • parse_args() → void
  • load_ignore_config() → void
  • should_ignore(name) → boolean
  • traverse_directory(path, parent_id, depth) → void
  • render_tree(root_id, prefix) → string
  • collect_files(path) → string[]
  • render_file_list(files) → string
  • output_terminal(tree_str, file_str, stats_str) → void
  • save_markdown(tree_str, file_str, stats_str, output_path) → void
  • compute_stats() → string
  • normalize_path(path) → string
  • format_size(bytes) → string

7. 脚本主体结构

#!/usr/bin/env bash
set -euo pipefail

# 常量定义
# 全局变量
# 工具函数normalize_path, format_size, usage
# 核心模块10个函数
# 主流程 main()

main() {
    parse_args "$@"
    load_ignore_config
    traverse_directory "$TARGET_PATH" "root" 0
    tree_output=$(render_tree "root" "")
    if $SHOW_FILES; then
        file_output=$(render_file_list "$(collect_files "$TARGET_PATH")")
    fi
    if $SHOW_STATS; then
        stats_output=$(compute_stats)
    fi
    output_terminal "$tree_output" "$file_output" "$stats_output"
    save_markdown "$tree_output" "$file_output" "$stats_output"
}

main "$@"

8. 验收标准对照

  • F013 接收路径输入 — 能正确解析相对路径和绝对路径 → normalize_path() + getopts
  • F014 加载忽略配置 — 支持.git、node_modules、__pycache__等 → 内置默认 + .treeignore 双层配置
  • F015 递归遍历目录 — 能正确跳过忽略的目录 → should_ignore() + 递归遍历
  • F016 生成目录树 — 使用├── ├──字符,缩进正确 → render_tree() 严格格式规范
  • F017 生成文件树 — 每个文件带完整路径 → collect_files() + render_file_list()
  • F018 终端输出 — 终端显示格式正确 → printf + 彩色支持
  • F019 Markdown 保存 — 默认保存到 tree_output.md → save_markdown() 代码块格式
  • F020 统计信息 — 统计信息准确 → compute_stats() 目录/文件/大小

9. 风险与约束

  • Bash 4.0 以下版本不支持关联数组 — 脚本头部版本检查,给出明确提示
  • 超大目录遍历性能 — 支持 --depth 限制深度
  • 文件名含特殊字符 — 使用 printf '%s' 安全输出
  • macOS du 与 Linux 差异 — 统一使用字节数后格式化
  • 符号链接循环 — inode 检测 + 已访问集合

10. 后续计划

  1. T021 Shell 代码编写(待本方案审批通过后激活)
  2. T022 功能测试验证
  3. T024 使用文档编写

文档结束