当前位置: 首页 > news >正文

导出指定文件夹下的文件结构 工具模块-Python

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):
        """
        参数说明:
        - root_path: 要扫描的根目录路径 
        - output_file: 输出文件路径 
        - fmt: 输出格式(txt/json/xml)
        - show_root: 是否显示根目录为树的顶层节点 
        - include_hidden_files: 是否包含隐藏文件 
        - include_hidden_dirs: 是否包含隐藏文件夹 
        - folders_only: 是否仅显示文件夹 
        - allowed_extensions: 允许的文件扩展名列表(例如 ['.py', '.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 [])
 
    def _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 _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']})")
            
            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", 
        fmt="txt",
        show_root=True,
        include_hidden_files=False,
        folders_only=False # ,
        # allowed_extensions=['.py', '.txt']
    )
    exporter.generate() 

相关文章:

  • PostgreSQL的学习心得和知识总结(一百六十九)|深入理解PostgreSQL数据库之 Group By 键值消除 的使用和实现
  • 【Pandas】pandas Series reindex
  • MySQL 的存储引擎简介
  • “深入浅出”系列之C++:(21)C++23
  • 使用 Ansys HFSS 对植入式医疗设备进行无线电力传输和 SAR 仿真
  • Day41 移除链表元素
  • 查询计算每一天的累计销售金额以及与前一天相比的销售金额增长额
  • 编译linux SDK
  • html网络安全工具源码 网络安全前端
  • 网络安全 逆向 apk 网络安全逆向分析
  • DeepSeek-学习与实践
  • 电容的温度系数分析
  • Qt中的MOC元对象系统内部原理介绍与开发应用
  • 【Git】初识Git 基础操作
  • DL/CV领域常见指标术语(FLOPS/mIoU/混淆矩阵/F1-measure)------一篇入门
  • C/C++流星雨
  • vue3 ref和reactive的区别
  • MOS管炸了,PWM“死区”时间得了解一下
  • 九联UNT403AS_晶晨S905L3S芯片_2+8G_安卓9.0_卡刷固件包
  • Python控制台信息记录全解析:从基础到生产级实践指南
  • 一海南救护车在西藏无任务拉警笛开道,墨脱警方:已处罚教育
  • 讲一个香港儿童的故事,《劏房的天空》获“周庄杯”特等奖
  • 支持企业增强战略敏捷更好发展,上海市领导密集走访外贸外资企业
  • 人民币对美元即期汇率盘中创半年新高,离岸市场升破7.2
  • 2024年度全国秋粮收购达3.45亿吨
  • 四姑娘山一游客疑因高反身亡,镇卫生院:送到时已很严重