18 KiB
18 KiB
目录树生成脚本 — 技术方案设计(Windows 平台)
任务 ID: T023 | 项目 ID: PROJ-20260509011
功能清单: F013-F020(8 个功能,全部审批通过)
运行平台: Windows
设计日期: 2026-05-16
设计者: 脚本架构师
1. 技术选型评估
1.1 功能级可行性分析(BAT vs Python)
| 功能编号 | 功能名称 | BAT 可行性 | Python 可行性 | 关键问题 |
|---|---|---|---|---|
| F013 | 接收路径输入 | ✅ 完全可行 | ✅ 完全可行 | BAT: %~1 即可;Python: argparse |
| F014 | 加载忽略配置 | ⚠️ 勉强可行 | ✅ 完全可行 | BAT 读取配置文件需逐行 for /f,无结构化解析能力 |
| F015 | 递归遍历目录 | ⚠️ 勉强可行 | ✅ 完全可行 | BAT for /r 可递归但无法灵活控制跳过逻辑 |
| F016 | 生成目录树(├── 字符) | ❌ 不可行 | ✅ 完全可行 | Windows CMD 默认代码页 936 (GBK) 无法正确显示 ├ ─ 等 Unicode 制表符;需 chcp 65001 且仍有渲染问题。BAT 字符串拼接缩进极其困难 |
| F017 | 生成文件树 | ⚠️ 勉强可行 | ✅ 完全可行 | BAT dir /s/b 可列出文件,但格式化输出困难 |
| F018 | 终端输出 | ⚠️ 有条件可行 | ✅ 完全可行 | BAT 需处理 chcp 65001 编码切换,输出重定向时易乱码 |
| F019 | Markdown 保存 | ⚠️ 勉强可行 | ✅ 完全可行 | BAT 可 echo > file.md,但 Markdown 结构化内容拼接繁琐 |
| F020 | 统计信息(目录数/文件数/总大小) | ❌ 困难 | ✅ 完全可行 | BAT 无原生文件大小累加能力,%%~zI 在 for 循环中可用但累加大文件时易溢出(BAT 整数仅支持 32 位) |
1.2 BAT 核心缺陷总结
- Unicode 制表符渲染:F016 要求输出
├──└──│等字符,Windows CMD 默认代码页下这些字符会显示为乱码。虽然chcp 65001可以切换 UTF-8,但在 Windows 10 之前的系统上存在严重兼容性问题,且输出重定向到文件时编码转换不可靠。 - 字符串处理:BAT 的字符串拼接、缩进管理极其笨拙,无法优雅实现树形缩进逻辑。
- 大文件统计:BAT 的整数运算限制在 32 位有符号范围(约 ±21 亿),总大小超过 2GB 时会溢出。
- 错误处理:BAT 缺乏结构化异常处理机制(try/catch),错误恢复困难。
- 配置解析:BAT 无法优雅解析结构化配置文件(JSON/INI),只能逐行文本处理。
1.3 评估结论
BAT 无法胜任 F016(目录树 Unicode 渲染)和 F020(大文件统计),其余功能也均存在明显缺陷。
2. 技术选型结论
最终选择:Python 3.8+(标准库,无第三方依赖)
理由:
| 维度 | 说明 |
|---|---|
| 功能覆盖 | 8 个功能全部可完美实现,无妥协 |
| Unicode 支持 | Python 原生 UTF-8 支持,├── 等字符渲染无问题 |
| 标准库 | pathlib、os、argparse、datetime 覆盖所有需求 |
| 文件大小 | Python 整数自动扩展,无溢出问题 |
| 跨版本兼容 | Python 3.8+ 覆盖 Windows 7 SP1 及以上所有版本 |
| 可维护性 | 代码结构清晰,模块化设计,易于扩展 |
| 部署 | 单文件 .py,用户只需安装 Python(Windows 10/11 可通过 Microsoft Store 一键安装) |
3. 项目结构
tree_generator/
├── tree_gen.py # 主程序(单文件,包含所有模块)
├── .treeignore # 忽略配置文件(可选,放在目标目录下)
├── tree_output.md # 默认输出文件(运行后生成)
└── README.md # 使用文档(由 Web 文档生成 Agent 创建)
设计原则:
- 主程序
tree_gen.py为单文件,不拆分为多模块,便于分发和使用 - 忽略配置文件
.treeignore放在目标目录下,遵循.gitignore惯例 - 输出文件默认在当前工作目录生成
4. 模块说明表
| 模块名 | 负责功能 | 输入 | 输出 | 依赖 |
|---|---|---|---|---|
ArgParser |
F013 路径输入 | 命令行参数 sys.argv |
解析后的配置对象(目标路径、输出路径、深度限制等) | argparse 标准库 |
IgnoreLoader |
F014 忽略配置 | 配置文件路径(.treeignore) |
忽略目录名称集合 set[str] |
pathlib 标准库 |
DirectoryScanner |
F015 递归遍历 | 目标路径 + 忽略集合 | 目录树结构(嵌套字典) | pathlib、os 标准库 |
TreeFormatter |
F016 目录树 + F017 文件树 | 目录树结构 | 格式化字符串(含 ├── 缩进) |
无额外依赖 |
TerminalOutput |
F018 终端输出 | 格式化字符串 | 终端显示(stdout) | sys 标准库(编码设置) |
MarkdownWriter |
F019 Markdown 保存 | 格式化字符串 + 输出路径 | .md 文件 |
pathlib 标准库 |
StatisticsCollector |
F020 统计信息 | 目录树结构 | 统计信息字典(目录数、文件数、总大小) | os 标准库 |
5. 技术选型结论总结
┌─────────────────────────────────────────────────────┐
│ 最终技术选型:Python 3.8+ 标准库 │
│ │
│ 核心文件:tree_gen.py(单文件,约 300-400 行) │
│ 配置文件:.treeignore(可选) │
│ 输出文件:tree_output.md(默认) │
│ │
│ 选择理由: │
│ 1. BAT 无法正确处理 Unicode 制表符(F016) │
│ 2. BAT 整数溢出问题(F020 大文件统计) │
│ 3. Python 标准库完全覆盖所有 8 个功能 │
│ 4. 单文件部署,零第三方依赖 │
└─────────────────────────────────────────────────────┘
6. 错误处理策略
6.1 异常分类与处理
| 异常类型 | 触发条件 | 处理策略 | 用户提示 |
|---|---|---|---|
PathNotFoundError |
目标路径不存在 | 捕获 FileNotFoundError,退出并提示 |
错误: 路径 "xxx" 不存在,请检查输入 |
PermissionError |
无权限访问目录 | 跳过该目录,记录警告,继续遍历 | 警告: 无权限访问 "xxx",已跳过 |
SymlinkLoopError |
符号链接循环 | 使用 pathlib.Path.resolve() 检测,跳过已访问路径 |
警告: 检测到符号链接循环,已跳过 |
EncodingError |
文件名含特殊字符 | 使用 errors='replace' 容错 |
静默替换,不中断 |
OutputWriteError |
无法写入输出文件 | 捕获 IOError/PermissionError,回退到仅终端输出 |
警告: 无法写入文件,仅显示到终端 |
InvalidConfigError |
忽略配置文件格式错误 | 使用默认忽略列表,记录警告 | 警告: 配置文件格式错误,使用默认配置 |
6.2 退出码规范
| 退出码 | 含义 |
|---|---|
| 0 | 成功完成 |
| 1 | 参数错误(路径不存在、格式错误) |
| 2 | 运行时错误(写入失败等) |
| 3 | 中断(Ctrl+C) |
7. 接口定义
7.1 数据流图
┌──────────┐ ┌──────────────┐ ┌─────────────────┐
│ 命令行参数 │────▶│ ArgParser │────▶│ Config 对象 │
│ sys.argv │ │ (F013) │ │ {path, output, │
└──────────┘ └──────────────┘ │ ignore, depth} │
└────────┬────────┘
│
┌───────────────────────────┼───────────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│IgnoreLoader │ │Directory │ │Statistics │
│(F014) │ │Scanner │ │Collector │
│ │ │(F015) │ │(F020) │
│.treeignore │ │ │ │ │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
▼ ▼ │
ignore_set tree_dict │
(set[str]) (嵌套字典) │
│ │
▼ │
┌──────────────────┐ │
│ TreeFormatter │◀────────────────────┘
│ (F016/F017) │
│ │
│ tree_str │
│ file_list_str │
└────────┬────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Terminal │ │ Markdown │ │ 统计信息 │
│ Output │ │ Writer │ │ 输出 │
│ (F018) │ │ (F019) │ │ │
│ │ │ │ │ │
│ stdout │ │ tree_output │ │ 目录/文件/ │
│ │ │ .md │ │ 总大小 │
└──────────────┘ └──────────────┘ └──────────────┘
7.2 核心数据结构
# Config 对象(ArgParser 输出)
Config = {
"target_path": Path, # 目标目录路径
"output_path": Path, # Markdown 输出路径(默认 tree_output.md)
"ignore_dirs": set[str], # 忽略目录名称集合
"max_depth": int | None, # 最大递归深度(None = 无限制)
"files_only": bool, # 仅显示文件模式
"dirs_only": bool, # 仅显示目录模式
}
# 目录树结构(DirectoryScanner 输出)
TreeDict = {
"name": str, # 目录/文件名
"path": Path, # 完整路径
"is_dir": bool, # 是否为目录
"children": list[TreeDict], # 子节点列表(目录时有效)
"size": int, # 文件大小(文件时有效)
}
# 统计信息(StatisticsCollector 输出)
Statistics = {
"dir_count": int, # 目录数量
"file_count": int, # 文件数量
"total_size": int, # 总大小(字节)
"total_size_human": str, # 人类可读大小(如 "1.23 GB")
}
7.3 模块间接口
| 调用方 | 被调用方 | 接口方法 | 参数 | 返回值 |
|---|---|---|---|---|
main() |
ArgParser |
parse_args() |
sys.argv[1:] |
Config |
main() |
IgnoreLoader |
load_ignores(config) |
Config |
set[str] |
main() |
DirectoryScanner |
scan(path, ignore_set, max_depth) |
Path, set[str], int|None |
TreeDict |
main() |
TreeFormatter |
format_tree(tree, style) |
TreeDict, str |
str |
main() |
TreeFormatter |
format_files(tree) |
TreeDict |
str |
main() |
TerminalOutput |
output(text) |
str |
None |
main() |
MarkdownWriter |
write(text, path) |
str, Path |
None |
main() |
StatisticsCollector |
collect(tree) |
TreeDict |
Statistics |
8. 忽略配置方案(F014)
8.1 配置文件格式
文件名:.treeignore(放在目标目录下)
# 忽略配置示例
# 每行一个目录名,支持 # 注释
.git
.gitignore
node_modules
__pycache__
*.pyc
.DS_Store
Thumbs.db
venv
.env
.idea
.vscode
dist
build
*.egg-info
8.2 内置默认忽略列表
当 .treeignore 不存在时,使用以下默认列表:
DEFAULT_IGNORE = {
".git", ".svn", ".hg", # 版本控制
"node_modules", "bower_components", # Node.js
"__pycache__", "*.pyc", ".pytest_cache", # Python
".idea", ".vscode", # IDE
"dist", "build", "target", # 构建产物
".DS_Store", "Thumbs.db", # 系统文件
"venv", ".venv", "env", # 虚拟环境
}
8.3 匹配规则
- 目录名精确匹配(不区分大小写,Windows 特性)
- 支持
*通配符(如*.pyc) - 忽略配置仅作用于目录级别,不递归检查文件内容
9. 树形输出格式规范(F016/F017)
9.1 目录树格式
项目根目录/
├── src/
│ ├── main.py
│ ├── utils/
│ │ ├── helper.py
│ │ └── config.py
│ └── models/
│ └── user.py
├── tests/
│ ├── test_main.py
│ └── test_utils.py
├── config.json
└── README.md
规则:
- 目录名后加
/后缀 - 分支符:
├──(有后续兄弟节点)/└──(最后一个节点) - 缩进线:
│(有后续兄弟节点)/(无后续兄弟节点) - 缩进单位:4 个字符(
│+ 3 空格 或 4 空格)
9.2 文件树格式
文件列表:
C:\project\src\main.py
C:\project\src\utils\helper.py
C:\project\src\utils\config.py
C:\project\src\models\user.py
C:\project\tests\test_main.py
C:\project\tests\test_utils.py
C:\project\config.json
C:\project\README.md
规则:
- 每个文件一行,带完整绝对路径
- 使用 Windows 风格路径分隔符
\ - 按字母顺序排序
9.3 统计信息格式
统计信息:
目录数: 5
文件数: 8
总大小: 24.5 KB (25,088 字节)
10. Markdown 保存方案(F019)
10.1 输出文件格式
# 目录树 — 项目根目录
> 生成时间: 2026-05-16 16:00:00
> 目标路径: C:\project
> 扫描深度: 无限制
## 目录结构
项目根目录/ ├── src/ │ ├── main.py │ └── utils/ │ └── helper.py ├── config.json └── README.md
## 文件列表
| # | 文件路径 |
|---|---------|
| 1 | `C:\project\src\main.py` |
| 2 | `C:\project\src\utils\helper.py` |
| 3 | `C:\project\config.json` |
| 4 | `C:\project\README.md` |
## 统计信息
- **目录数:** 3
- **文件数:** 4
- **总大小:** 1.2 KB (1,234 字节)
10.2 保存策略
- 默认文件名:
tree_output.md(当前工作目录) - 可通过
-o/--output参数指定自定义路径 - 文件已存在时覆盖写入(不追加)
- 编码:UTF-8 with BOM(Windows 记事本兼容)
11. 命令行接口设计
usage: tree_gen.py [-h] [-o OUTPUT] [-d DEPTH] [-f] [-D] [-i IGNORE_FILE] [path]
目录树生成脚本 - Windows 平台
positional arguments:
path 目标目录路径(默认: 当前目录)
options:
-h, --help 显示帮助信息
-o OUTPUT, --output OUTPUT
Markdown 输出文件路径(默认: tree_output.md)
-d DEPTH, --depth DEPTH
最大递归深度(默认: 无限制)
-f, --files-only 仅显示文件树
-D, --dirs-only 仅显示目录树
-i IGNORE_FILE, --ignore IGNORE_FILE
忽略配置文件路径(默认: 目标目录下的 .treeignore)
使用示例
# 扫描当前目录
python tree_gen.py
# 扫描指定目录
python tree_gen.py C:\Users\test\project
# 指定输出文件和深度
python tree_gen.py C:\project -o output.md -d 3
# 仅显示文件
python tree_gen.py C:\project -f
# 自定义忽略配置
python tree_gen.py C:\project -i my_ignore.txt
12. 编码规范
| 项目 | 规范 |
|---|---|
| 文件编码 | UTF-8(Python 源文件) |
| 输出编码 | UTF-8 with BOM(Markdown 文件) |
| 终端编码 | UTF-8(通过 sys.stdout.reconfigure(encoding='utf-8') 设置) |
| 行尾符 | LF(Python 标准) |
| 缩进 | 4 空格 |
| Python 版本 | 3.8+ |
13. 后续任务
| 任务 | 负责 Agent | 状态 |
|---|---|---|
| T021: Python 代码实现 | BAT 编码 Agent(实际应为 Python 编码 Agent) | 待激活 |
| T022: 功能测试验证 | 测试验证 Agent | 待激活 |
| T024: 使用文档编写 | Web 文档生成 Agent | 待激活 |
文档结束。等待审批后进入编码阶段。