# tree.sh — 目录树生成脚本 一个用纯 Bash 编写的轻量级目录树生成工具,支持忽略配置、递归遍历、文件列表、Markdown 导出和统计信息。无需安装任何依赖,开箱即用。 **版本:** 1.0.0 --- ## 功能特性 | 功能 | 说明 | |------|------| | **目录树生成** | 使用 `├──` / `└──` 字符生成标准树形结构,目录在前、文件在后,按字母排序 | | **文件列表** | 可选生成完整文件列表(`-f`),显示所有文件的绝对路径 | | **忽略配置** | 内置 30+ 种常见忽略模式(`.git`、`node_modules`、`__pycache__` 等),支持 `.treeignore` 自定义 | | **深度限制** | 通过 `-d` 参数限制递归深度,避免过深遍历 | | **Markdown 导出** | 默认保存为 `tree_output.md`,也可自定义输出路径 | | **统计信息** | 自动统计目录数、文件数和总大小(自动转换为 B / KB / MB / GB) | | **循环检测** | 基于 inode 检测符号链接循环,防止无限递归 | | **权限处理** | 对无权限目录显示 `[Permission denied]`,不会中断执行 | --- ## 环境要求 - **操作系统:** Linux 或 macOS - **Shell:** Bash 4.0 或更高版本 - **依赖:** 无(仅使用 Bash 内置命令和 `stat`、`awk`、`basename`、`dirname`、`mkdir` 等标准工具) 检查 Bash 版本: ```bash bash --version ``` --- ## 安装方法 **零安装。** 直接下载或克隆脚本后即可运行: ```bash chmod +x tree.sh ./tree.sh -p /path/to/target ``` 也可以将脚本放到 PATH 中的某个目录,方便全局调用: ```bash sudo cp tree.sh /usr/local/bin/tree.sh tree.sh -p /path/to/target ``` --- ## 使用方法 ### 基本用法 ```bash # 生成当前目录的树形结构 ./tree.sh # 生成指定目录的树形结构 ./tree.sh -p /home/user/project # 使用相对路径 ./tree.sh -p ../some-project ``` ### 命令行选项 | 选项 | 简写 | 说明 | 默认值 | |------|------|------|--------| | `--path <路径>` | `-p` | 指定目标目录 | 当前目录 (`.`) | | `--output <文件>` | `-o` | 指定 Markdown 输出文件 | `tree_output.md` | | `--depth ` | `-d` | 限制递归深度(正整数) | 无限制 | | `--files` | `-f` | 同时生成文件列表 | 关闭 | | `--no-stats` | `-s` | 不显示统计信息 | 显示 | | `--help` | `-h` | 显示帮助信息 | — | | `--version` | `-v` | 显示版本信息 | — | ### 常用示例 ```bash # 生成当前目录的完整树(含文件列表和统计) ./tree.sh -f # 只查看前 2 层目录结构 ./tree.sh -d 2 # 生成项目树并保存到自定义文件 ./tree.sh -p /var/www/myapp -o project-tree.md # 深度 3 + 文件列表 + 保存 ./tree.sh -p ./src -d 3 -f -o src-tree.md # 仅终端输出,不保存 Markdown 文件(重定向) ./tree.sh -p . -s > /dev/null # 查看帮助 ./tree.sh -h # 查看版本 ./tree.sh -v ``` --- ## 配置说明 ### 内置忽略列表 脚本默认忽略以下目录和文件类型: **版本控制:** - `.git`、`.svn`、`.hg` **包管理 & 缓存:** - `node_modules`、`__pycache__`、`.cache`、`.tox`、`.eggs` **构建产物:** - `dist`、`build`、`.next`、`.nuxt`、`.output`、`.vercel`、`.terraform`、`.vagrant` **IDE & 编辑器:** - `.idea`、`.vscode` **编译产物:** - `*.pyc`、`*.pyo`、`*.egg-info`、`*.swp`、`*.swo`、`*.swn`、`*.class`、`*.o`、`*.so`、`*.dylib` **系统文件:** - `.DS_Store` ### 自定义忽略配置 在目标目录下创建 `.treeignore` 文件,每行一个忽略模式: ```bash # .treeignore 示例 # 注释以 # 开头 # 忽略特定目录 logs tmp *.log # 忽略特定文件类型 *.bak *.tmp *.orig # 忽略特定名称 .env.local coverage ``` **规则:** - 空行和以 `#` 开头的行会被忽略(作为注释) - 支持精确匹配(如 `logs`)和 glob 通配符(如 `*.log`) - 忽略模式会追加到内置列表之后,不会覆盖内置规则 --- ## 使用示例 ### 示例 1:基本目录树 ```bash $ ./tree.sh -p ./my-project ``` **终端输出:** ``` my-project/ ├── src/ │ ├── main.sh │ ├── utils/ │ │ ├── helpers.sh │ │ └── validators.sh │ └── config.sh ├── tests/ │ ├── test_main.sh │ └── test_utils.sh ├── README.md └── tree_output.md Files: /home/user/my-project/src/main.sh /home/user/my-project/src/utils/helpers.sh /home/user/my-project/src/utils/validators.sh /home/user/my-project/src/config.sh /home/user/my-project/tests/test_main.sh /home/user/my-project/tests/test_utils.sh /home/user/my-project/README.md /home/user/my-project/tree_output.md Statistics: Directories: 4 Files: 8 Total size: 12.34 KB ``` ### 示例 2:限制深度 ```bash $ ./tree.sh -p ./my-project -d 2 ``` **输出:** ``` my-project/ ├── src/ │ ├── main.sh │ ├── utils/ │ └── config.sh ├── tests/ │ ├── test_main.sh │ └── test_utils.sh ├── README.md └── tree_output.md ``` ### 示例 3:生成 Markdown 文件 ```bash $ ./tree.sh -p ./my-project -f -o my-tree.md ``` **生成的 `my-tree.md` 内容:** ```markdown # Directory Tree Path: `./my-project` ``` my-project/ ├── src/ │ ├── main.sh │ ├── utils/ │ │ ├── helpers.sh │ │ └── validators.sh │ └── config.sh ├── tests/ │ ├── test_main.sh │ └── test_utils.sh ├── README.md └── tree_output.md ``` ## Files /home/user/my-project/src/main.sh ... ## Statistics - **Directories:** 4 - **Files:** 8 - **Total size:** 12.34 KB ``` ### 示例 4:结合 .treeignore 使用 ```bash # 创建 .treeignore echo -e "*.log\ntmp\ncoverage" > .treeignore # 运行脚本(自动加载 .treeignore) ./tree.sh -p . ``` --- ## 注意事项 1. **路径必须存在且为目录**:如果指定的路径不存在或不是目录,脚本会报错退出(退出码 2)。 2. **深度参数必须为正整数**:`-d` 参数必须传入大于 0 的整数,否则报错退出(退出码 1)。 3. **符号链接循环检测**:脚本基于 inode 检测循环引用。如果检测到循环,会显示 `[cycle detected, skipped]` 并跳过,不会无限递归。 4. **权限问题**:遇到无权限读取的目录时,会显示 `[Permission denied]` 并继续处理其他目录,不会中断整个流程。 5. **输出文件目录自动创建**:如果 `-o` 指定的输出路径中的目录不存在,脚本会自动创建。 6. **Markdown 文件始终生成**:脚本每次运行都会同时输出到终端和保存 Markdown 文件(默认 `tree_output.md`)。终端输出和 Markdown 内容一致。 7. **大小写敏感**:忽略模式匹配区分大小写。 8. **隐藏文件**:以 `.` 开头的隐藏文件/目录会被正常遍历(除非被忽略规则匹配)。 9. **退出码**: - `0`:成功 - `1`:参数错误 - `2`:路径无效 - `3`:写入失败 --- ## 项目信息 - **项目 ID:** PROJ-20260509011 - **功能覆盖:** F013–F020(8 个功能全部测试通过)