Files
tree-generator/tree_architecture_design.md
2026-05-16 14:57:11 +08:00

379 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 目录树生成脚本 - 架构设计文档
项目 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 关联数组存储树结构
```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 全局变量定义
```bash
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. 脚本主体结构
```bash
#!/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 使用文档编写
---
*文档结束*