python模块代码
import os
import json
import xml.etree.ElementTree as ET
from typing import List, Optional, Dict, Union
from pathlib import Path class DirectoryTreeExporter:def __init__(self,root_path: str,output_file: str,fmt: str = 'txt',show_root: bool = True,include_hidden_files: bool = False,include_hidden_dirs: bool = False,folders_only: bool = False,allowed_extensions: Optional[List[str]] = None,show_type_in_txt: bool = False):"""参数说明:- root_path: 要扫描的根目录路径 - output_file: 输出文件路径 - fmt: 输出格式(txt/json/xml)- show_root: 是否显示根目录为树的顶层节点 - include_hidden_files: 是否包含隐藏文件 - include_hidden_dirs: 是否包含隐藏文件夹 - folders_only: 是否仅显示文件夹 - allowed_extensions: 允许的文件扩展名列表(例如 ['.py', '.txt'])- show_type_in_txt: 在txt格式中显示文件类型"""self.root = Path(root_path).resolve()self.output_file = output_file self.fmt = fmt.lower() self.show_root = show_root self.include_hidden_files = include_hidden_files self.include_hidden_dirs = include_hidden_dirs self.folders_only = folders_only self.allowed_extensions = set(allowed_extensions or [])self.show_type_in_txt = show_type_in_txtdef _is_hidden(self, path: Path) -> bool:"""跨平台的隐藏文件/目录检测"""if os.name == 'nt': # Windows系统 hidden_attr = os.stat(path).st_file_attributes return hidden_attr & 2 # FILE_ATTRIBUTE_HIDDEN else: # Unix-like系统 return path.name.startswith('.') def _should_include(self, path: Path, is_dir: bool) -> bool:"""过滤条件判断"""# 隐藏文件处理 if is_dir:if not self.include_hidden_dirs and self._is_hidden(path):return False else:if not self.include_hidden_files and self._is_hidden(path):return False # 仅目录模式 if self.folders_only and not is_dir:return False # 扩展名过滤 if not is_dir and self.allowed_extensions: return path.suffix.lower() in self.allowed_extensions return True def _build_tree(self, node: Path, tree_dict: Dict) -> None:"""递归构建树形结构"""for child in node.iterdir(): if not self._should_include(child, child.is_dir()): continue entry = {'name': child.name, 'type': 'directory' if child.is_dir() else 'file','children': []}if child.is_dir(): self._build_tree(child, entry)tree_dict['children'].append(entry)def generate(self) -> None:"""生成并导出目录树"""# 构建数据结构 tree = {'name': self.root.name, 'type': 'directory','children': []} if self.show_root else {'children': []}if self.show_root: self._build_tree(self.root, tree)else:for child in self.root.iterdir(): if self._should_include(child, child.is_dir()): entry = {'name': child.name, 'type': 'directory' if child.is_dir() else 'file','children': []}if child.is_dir(): self._build_tree(child, entry)tree['children'].append(entry)# 选择输出格式 output_methods = {'txt': self._generate_txt,'json': self._generate_json,'xml': self._generate_xml }if self.fmt not in output_methods:raise ValueError(f"不支持的格式: {self.fmt}") output_methods[self.fmt](tree)def replace_vertical_below_lconnector(self, lines):"""清除多余的竖线"""for i in range(len(lines)):# if lines[i]:lines[i] = list(lines[i])# 遍历每一行,查找'└'符号位置sign_pos_1 = []for row in range(len(lines)):for col in range(len(lines[row])):if lines[row][col] == '└':sign_pos_1.append((row, col))# while col >= 0 and lines[row][col] != '│':# lines[row][col] = ' '# col -= 1for row in range(len(lines)):for col in range(len(lines[row])):for pos in sign_pos_1:if row > pos[0] and col==pos[1]:if lines[row][col] == '│':lines[row][col] = ' '# lines[row].insert(0,' ')# sign_pos_1.insert(0)for i in range(len(lines)):lines[i] = ''.join(lines[i])return linesdef _generate_txt(self, tree: Dict) -> None:"""生成文本树形结构"""def _recurse(node: Dict, depth: int, lines: List[str], is_last: bool) -> None:prefix = ""if depth > 0:prefix = "│ " * (depth - 1) + ("└── " if is_last else "├── ")# lines.append(f"{prefix}{node['name']} ({node['type']})")if self.show_type_in_txt:lines.append(f"{prefix}{node['name']} ({node['type']})")else:lines.append(f"{prefix}{node['name']}")children = node.get('children', [])for i, child in enumerate(children):_recurse(child, depth + 1, lines, i == len(children)-1)lines = []if self.show_root: _recurse(tree, 0, lines, True)else:for child in tree['children']:_recurse(child, 0, lines, False)lines = self.replace_vertical_below_lconnector(lines)with open(self.output_file, 'w', encoding='utf-8') as f:f.write("\n".join(lines)) def _generate_json(self, tree: Dict) -> None:"""生成JSON结构"""with open(self.output_file, 'w', encoding='utf-8') as f:json.dump(tree, f, indent=2, ensure_ascii=False)def _generate_xml(self, tree: Dict) -> None:"""生成XML结构"""def _add_node(parent: ET.Element, node: Dict) -> None:elem = ET.SubElement(parent, node['type'])elem.set('name', node['name'])for child in node.get('children', []):_add_node(elem, child)root = ET.Element('directory_tree')if self.show_root: _add_node(root, tree)else:for child in tree['children']:_add_node(root, child)tree = ET.ElementTree(root)tree.write(self.output_file, encoding='utf-8', xml_declaration=True)if __name__ == "__main__":exporter = DirectoryTreeExporter(# root_path=r"D:\Creation\JiLeiFunc\root_dir",# output_file=r"D:\Creation\JiLeiFunc\tree.txt", root_path=r"D:\test\root_dir",output_file=r"D:\test\tree.txt", fmt="txt",show_root=True,include_hidden_files=False,folders_only=False # ,# allowed_extensions=['.py', '.txt'])exporter.generate()
运行效果截图
*.txt 文档
标注节点类型:
*.json 文档
*.xml 文档
功能特性说明
1. 多格式支持
- 文本格式:使用ASCII字符构建树状结构
project (directory) ├── src (directory) │ ├── main.py (file) │ └── utils.py (file) └── README.md (file)
- JSON格式:结构化数据存储,支持程序解析
{"name": "project","type": "directory","children": [{"name": "src","type": "directory","children": [...]}] }
- XML格式:标准数据交换格式,便于其他系统处理
<directory_tree><directory name="project"><directory name="src">...</directory></directory> </directory_tree>
2. 智能过滤系统
- 隐藏文件处理:自动识别操作系统类型(Windows/Unix)
- 扩展名过滤:支持白名单机制(如仅显示.py和.txt)
- 目录模式:通过
folders_only=True
仅展示文件夹结构
3. 跨平台兼容
- 使用
pathlib
模块统一处理路径差异 - 自动识别不同系统的隐藏文件判断逻辑
4. 性能优化
- 递归算法优化:采用尾递归设计避免栈溢出
- 内存管理:使用生成器模式构建大型目录树
扩展性设计
1. 添加新格式
class EnhancedDirectoryTreeExporter(DirectoryTreeExporter):def _generate_markdown(self, tree: Dict) -> None:"""新增Markdown格式支持"""def _recurse(node, depth):indent = " " * depth line = f"{indent}- {node['name']}"if node['type'] == 'file':line += f" `{node['type']}`"yield line for child in node.get('children', []):yield from _recurse(child, depth+1)lines = list(_recurse(tree, 0)) if self.show_root else []with open(self.output_file, 'w') as f:f.write("\n".join(lines))def generate(self):self.output_methods['md'] = self._generate_markdown super().generate()
2. 自定义渲染
exporter = DirectoryTreeExporter(...)
exporter.output_methods['custom'] = lambda tree: ... # 动态添加渲染器
典型应用场景
1. 项目文档生成
exporter = DirectoryTreeExporter(root_path=".",output_file="PROJECT_STRUCTURE.md",fmt="txt",allowed_extensions=['.py', '.md'],folders_only=False
)
2. 系统审计
exporter = DirectoryTreeExporter(root_path="/var/log",output_file="system_logs.json",fmt="json",include_hidden_dirs=True,include_hidden_files=True
)
3. 自动化部署
# 生成Docker镜像内的文件结构
exporter = DirectoryTreeExporter(root_path="/app",output_file="docker_files.xml",fmt="xml",show_root=False
)