python学习—探索嵌套文件夹,统计文件数量及构建索引表格

系列文章目录

python学习—合并TXT文本文件


功能说明

日常工作中,有时候会统计嵌套文件夹中的文件数量,最好还要分出类型,方便作为目录管理。
使用批处理工具,可以是实现将文件列表统一写入某个txt文件或者表格中,但是所有文件夹(包括内部嵌套的文件夹)信息都在一起了,管理起来还是不太直观方能。

本代码目标为:

  • 1 指定最外层的文件夹路径,给最终的表格起个名字;
  • 2 代码运行后,会生成最终统计表格工作簿;
  • 3 首个sheet表格为总目录,每行显示文件夹及内部文件数量;
  • 4 后面的sheet表格,详细列表每个文件夹内的文件名,可以用后缀名做分类;
  • 5 输出代码运行的时间。

1 准备工作

代码运行环境为python3,支持中文,代码需要填写2个参数:(1)拟统计的文件夹路径,(2)给定最终表格名称及路径。
测试目录为“D:\mulu”,在该文件夹内存放多个txt格式文本文件,还有嵌套文件夹。最终表格命名为"D:\文件统计表.xlsx"。

(知识点) 批处理文件 .bat
批处理程序是一种在Windows操作系统下运行的脚本文件,它可以自动执行一系列命令或任务。
使用方法是:新建一个txt文本文件,在文本文件中编辑批处理程序,关闭txt文本文件,修改后缀名为“.bat”,双击 该文件,运行即可。
批处理程序可以接受参数作为输入,这些参数可以用于控制程序的行为或提供必要的数据。

显示指定目录中的文件列表,使用命令 : dir
参数有 :
/a 显示所有文件,包括隐藏文件和系统文件;
/b 以简洁格式显示文件名;
/s 在定目录及其子目录中搜索文件,即搜索嵌套文件夹;

  dir  /b/s> list.xls

该命令的作用是在 当前目录 (存放 批处理文件的位置) 及其子目录中搜索所有的文件,并将结果保存到名为list.xls的文件中。结果如下:
666

此外,还可以指定 搜索 文件类型,即 指定文件的后缀 ,如 .jpg 、*.txt 、文件名 用 通配符 * 星号代替。

   dir /b/s  *.txt> list.xls
   dir *.txt /b/s > list.xls

文件类型也可以放在 参数前面或者后面,均可以,但是要在 " > " 前面。

(知识点) python创建并填写Excel表格
python支持微软格式的Excel表格,可以创建、修改、填写等,需要安装 openpyxl 库。

——创建工作簿: 新建的工作簿,不能为空,故默认有1个名称为 sheet 的工作表。最后,有保存语句。

wb = openpyxl.Workbook()  #新建一个空的工作簿,目前在内存里存在,因为 表格没有名称。
a = wb.sheetnames
print(a)
# ['Sheet']
wb.save('新建表格.xlsx')  #关键语句,最后 ,别忘记保存文件,否则,表格只存在于内存中

——改名: 修改工作表的名称

sheet.title = 'syq Sheet'  #修改表格名称
print(wb.sheetnames)
# ['syq Sheet']

——新建表格: 在工作簿中新建工作表,没起名字的话,默认续排号。可以指定表格位置和名称。

wb.create_sheet()
print(wb.sheetnames)
# ['Sheet', 'Sheet1']
wb.create_sheet(index=0, title='First Sheet')
print(wb.sheetnames)
# ['First Sheet', 'Sheet', 'Sheet1']

——删除表格: 删除指定名称 的工作表

del wb['Sheet1']
print(wb.sheetnames)
# ['First Sheet', 'Sheet']

——打开表格: 打开 已知位置的工作簿,改名另存为。

wb = openpyxl.load_workbook('example.xlsx')  #该行是打开命令,需要表格存在,否则报错
sheet = wb.active   # 指定 活动工作簿
sheet.title = 'Spam Spam Spam'
wb.save('example_copy.xlsx')  #另存为

——向单元格写数据: 将 值写入单元格,很像 给字典的键写value值。

wb = openpyxl.load_workbook(f'新建.xlsx')  #此语句是打开
sheet = wb['Sheet']
sheet['A1'] = 'Hello,world!'
wb.save('新建.xlsx')
print(sheet['A1'].value)
# Hello,world!

——更新单元格: 工作表中的单元格sheet.cell,有两个参数来定位,行 row,列 column,如A1,B2,跟office一致。
需要指定行数和列数,从1开始计数,因为表格没有0行,0列,无意义。

//已知有成绩单,第一列为科目名称,第二列为成绩,根据科目名称更新3科成绩。
grades_updates = {'数学': 80, '语文': 90, '体育': 100}
#遍历表格
for rowNum in range(2, sheet.max_row):  # 第一行为 字段名,故从第2 行开始查找。
    CourseName = sheet.cell(row=rowNum, column=1).value   #第一列  名称
    if CourseName in grades_updates:
        sheet.cell(row=rowNum, column=2).value = grades_updates[CourseName]  #第二列  成绩

——超链接: 给单元格设置超链接,点击后链接到工作簿中的某处,或者网址等。

cell = sheet1.cell(row=1, column=1)
cell.hyperlink = "#Sheet1!A1"   # 这里的 井号 “#”  代表 同一个  工作簿中的
cell.hyperlink = "https://www.example.com"  # 超链接到 网址
cell(row=1, column=1).value = "点击这里"   # 可以设置超链接  单元格 显示的 值

——单元格格式: 可以设置,颜色,下划线,字体等。

blue_font = Font(color="0000FF", underline="single")
cell.font = blue_font

——关闭工作簿: 保存工作簿之后,记得 关闭 工作簿,清除进程锁。

workbook.save("XXXXX.xlsx")
workbook.close()

2 第一版代码

第一版本的代码,主要实现一个遍历文件夹,成功导出到excel表格中,区分目录页和分表。

(1) 新建工作簿

首先,新建一个工作簿,然后添加“目录页”工作表sheet,保存,方便后续调用。

wb = openpyxl.Workbook()  # 新建一个空的工作簿
wb.active.title = r'目录页'
wb.save(summaryTable)

(2) 打开工作簿,遍历文件夹

工作簿在打开的状态下,进行遍历文件夹,数据写入工作,在最后需要 关闭工作簿进行保存。

wb = openpyxl.load_workbook(summaryTable)  # 打开工作簿
# 遍历文件夹,3个参数:路径、文件夹名称、文件名称集合
for folderName, subfolders, filenames in os.walk(root_directory):
    linevalue = []   # 每行的 描述
    num += 1   #   序号

(3) 填写目录页

目录页,第1列填写 序号,第2列 填写 描述语句 produceName。

    #  目录页
    produceName = '文件夹<' + folderName + '>中有文件数量:' + str(len(filenames))
    linevalue.append(produceName)
    sheetAll = wb['目录页']
    sheetAll.cell(row=num, column=1).value = num  # 目录页  第一列 序号
    sheetAll.cell(row=num, column=2).value = produceName  # 目录页   第二列 详细描述  

(4) 填写分页

分页表格,第1列填写 路径,第2列 首行填写 描述语句 produceName,第二行 开始填写 文件名列表。

     for filename in filenames:
         linevalue.append(filename)
     #  详细页
     wb.create_sheet(str(num))  # 新建详细表格
     sheet = wb[str(num)]  # 新建详细表格 表名称
     for rowNum in range(1, len(filenames) + 2):
         sheet.cell(row=rowNum, column=1).value = folderName  # 详细页 第一列  文件夹名称
         sheet.cell(row=rowNum, column=2).value = linevalue[(rowNum - 1)]  # 详细页 第二列  文件名

(5) 最后,保存工作簿

从开始的打开表格,到这里的 保存表格,填写的内容存储到表格中。

wb.save(summaryTable)

(6) 组装成函数,给定参数,调用函数运行

组装成函数 TotalNumber(参数1, 参数2) ,方便管理,提高效率。

def main():
    root_directory = r'D:\mulu'  # 参数1 例如:E:\\test
    summaryTable = r'D:\文件统计表.xlsx'  # ———最终汇总表的存放位置 及 表格名称,例如:D:\\文件统计表.xlsx
    TotalNumber(root_directory, summaryTable) 

再弄一个 代码运行计时语句。

    start_time = time.time()
    end_time = time.time()
    execution_time = end_time - start_time  # 计算代码执行时间(单位为秒)
    # 将执行时间转换为时、分、秒的格式
    hours = int(execution_time // 3600)
    minutes = int((execution_time % 3600) // 60)
    seconds = float(execution_time % 60)
    # 输出格式化后的时间
    formatted_time = f"{hours:02d}:{minutes:02d}:{seconds:.2f}"
    print("代码执行时间:", formatted_time)

(7) 第一版完整代码

import time
import openpyxl
import os


def TotalNumber(root_directory, summaryTable):
    num = 0
    wb = openpyxl.Workbook()  # 新建一个空的工作簿
    wb.active.title = r'目录页'
    wb.save(summaryTable)
    wb = openpyxl.load_workbook(summaryTable)  # 打开工作簿

    for folderName, subfolders, filenames in os.walk(root_directory):
        linevalue = []
        num += 1

        #  目录页
        produceName = '文件夹<' + folderName + '>中有文件数量:' + str(len(filenames))
        linevalue.append(produceName)
        sheetAll = wb['目录页']
        sheetAll.cell(row=num, column=1).value = num  # 目录页  第一列 序号
        sheetAll.cell(row=num, column=2).value = produceName  # 目录页   第二列 描述
        
        #  分表 详细页
        for filename in filenames:
            linevalue.append(filename)
        wb.create_sheet(str(num))  # 新建详细表格
        sheet = wb[str(num)]  # 新建详细表格 表名称
        for rowNum in range(1, len(filenames) + 2):
            sheet.cell(row=rowNum, column=1).value = folderName  # 详细页 第一列  文件夹名称
            sheet.cell(row=rowNum, column=2).value = linevalue[(rowNum - 1)]  # 详细页 第二列  文件名

    wb.save(summaryTable)


def main():
    start_time = time.time()
    root_directory = r'D:\mulu'  # 参数1:想要统计的文件夹
    summaryTable = r'D:\文件统计表.xlsx'  # 参数2: 最终表格的路径 及 表格名称
    TotalNumber(root_directory, summaryTable)  #调用函数

    end_time = time.time()
    execution_time = end_time - start_time  # 计算代码执行时间(单位为秒)

    # 将执行时间转换为时、分、秒的格式
    hours = int(execution_time // 3600)
    minutes = int((execution_time % 3600) // 60)
    seconds = float(execution_time % 60)
    # 输出格式化后的时间
    formatted_time = f"{hours:02d}:{minutes:02d}:{seconds:.2f}"
    print("代码执行时间:", formatted_time)


if __name__ == '__main__':  # 象征意义,代表  main是程序的入口
    main()

结果如下图:
3

3 第二版代码

第一版的代码,主要功能基本实现了,第二版本主要 整理一下,集成为函数,提高效率。

(1) 文件总数计数函数

统计文件夹及嵌套文件夹内,所有文件的总数。给 目录页首行 输出使用。

def count_files_in_directory(root_dir):
    count_sum = 0
    for _, _, filenames in os.walk(root_dir):
        count_sum += len(filenames)
    return count_sum

短横线 通常被用作占位符,表示不需要使用的变量。
在这里,os.walk() 函数返回的元组包含三个元素:文件夹路径、文件夹名称 和 文件名列表集合。
由于此处只对 第3个元素:文件名列表集合 感兴趣,因此可以使用占位符 “ _ ” 来表示不需要的变量。

(2) 每个文件夹内的文件数量统计

新建 列表 summary,每层文件夹名称 和 内部的文件数,作为列表的一组数据。

def generate_directory_summary(root_dir):
    summary = []
    for folder_name, _, filenames in os.walk(root_dir):
        summary.append((folder_name, len(filenames)))
    return summary

由于我们只对 文件夹名称 和 文件名称集合 感兴趣,因此可以使用占位符“ _ ”来表示不需要的变量。

(3) 填写目录页

def write_directory_summary_to_workbook(count_sum, summary, directory_sheet):
    directory_sheet.title = "目录页"
    # 首行 ,字段名称
    directory_sheet.cell(row=1, column=1, value="序号")
    directory_sheet.cell(row=1, column=2, value="文件夹名称")
    directory_sheet.cell(row=1, column=3, value="文件数量")
    # 第2行,总数量
    directory_sheet.cell(row=2, column=1, value=0)
    directory_sheet.cell(row=2, column=2, value="文件总数量")
    directory_sheet.cell(row=2, column=3, value=count_sum)
    # 第3行 开始,每个文件夹内的文件数量
    # for i, (folder_name, file_count) in enumerate(summary, start=3):   # 此方法理解较直观
    for i, (folder_name, file_count) in zip(itertools.count(start=3), summary):
        directory_sheet.cell(row=i, column=1, value=i - 2)
        directory_sheet.cell(row=i, column=2, value=folder_name)
        directory_sheet.cell(row=i, column=3, value=file_count)

(4) 填写分页

def write_files_in_directory_to_workbook(folder_name, workbook, sheet_name):
    file_list = os.listdir(folder_name)
    sheet = workbook.create_sheet(sheet_name)
    # 首行 ,字段名称
    sheet.cell(row=1, column=1, value="文件夹名称")
    sheet.cell(row=1, column=2, value="文件名")
    sheet.cell(row=1, column=3, value="类型")
    # for i, filename in enumerate(file_list, start=2):    # 此方法理解较直观
    for i, filename in zip(itertools.count(start=2), file_list):
        file_path = os.path.join(folder_name, filename)
        sheet.cell(row=i, column=1, value=folder_name)
        sheet.cell(row=i, column=2, value=filename)
        # 判定文件 和 文件夹
        if os.path.isfile(file_path):
            # 获取文件后缀名
            file_extension = os.path.splitext(filename)[1][1:]
            sheet.cell(row=i, column=3, value=file_extension)
        elif os.path.isdir(file_path):
            sheet.cell(row=i, column=3, value="文件夹")

(5) 调用以上函数的 函数

def generate_file_summary(root_dir, workbook):
    summary = generate_directory_summary(root_dir)
    count_sum = count_files_in_directory(root_dir)
    directory_sheet = workbook.active
    write_directory_summary_to_workbook(count_sum, summary, directory_sheet)
    for i, (folder_name, _) in enumerate(summary, start=1):
        write_files_in_directory_to_workbook(folder_name, workbook, str(i))

(6) 给 目录页 的每行,设置超链接,链接到后面的分表

这一步,需要在上面步骤生成结果表格完毕之后,对成果表格进行的超链接设置,故放在 步骤(5) 调用函数的外面。

def setup_hyperlinks(workbook_path):
    """
    目录页设置超链接
    """
    wb = openpyxl.load_workbook(workbook_path)
    sheet_names = set(wb.sheetnames)
    sheet1 = wb['目录页']

    # 创建一个蓝色字体样式,带下划线
    blue_font = Font(color="0000FF", underline="single")
    max_row = sheet1.max_row
    for rowNum in range(2, max_row + 1):
        num = sheet1.cell(row=rowNum, column=1).value
        if str(num) in sheet_names:
            cell = sheet1.cell(row=rowNum, column=1)
            cell.hyperlink = f"#{num}!A1"
            cell.font = blue_font

    wb.save(workbook_path)
    wb.close()

(7) 使用 main() 函数,启动程序

使用 main() 函数启动函数,其中使用 try - finally块 来确保文件被正确关闭。
仍然有代码运行计时。

def main():
    root_dir = r"D:\mulu"     # 参数1  统计的目录
    summary_filename = r"D:\文件统计表.xlsx"    # 参数2   最终保存的表格路径及名称
    workbook = openpyxl.Workbook()
    start_time = time.time()  # 代码运行计时开始
    # 用常规的try - finally块来确保文件被正确关闭
    try:
        generate_file_summary(root_dir, workbook)
        workbook.save(summary_filename)
        setup_hyperlinks(summary_filename)
    finally:
        workbook.close()

    end_time = time.time() - start_time  # 计算代码执行时间(单位为秒)
    # 将执行时间转换为时、分、秒的格式
    hours = int(end_time // 3600)
    minutes = int((end_time % 3600) // 60)
    seconds = float(end_time % 60)
    formatted_time = f"{hours:02d}:{minutes:02d}:{seconds:00.2f}"
    print("代码执行时间:", formatted_time)

(8) 完整代码

完整代码如下:

import time
import openpyxl
from openpyxl.styles import Font
import os
import itertools


def count_files_in_directory(root_dir):
    count_sum = 0
    for _, _, filenames in os.walk(root_dir):
        count_sum += len(filenames)
    return count_sum


def generate_directory_summary(root_dir):  
    summary = []
    for folder_name, _, filenames in os.walk(root_dir):
        summary.append((folder_name, len(filenames)))
    return summary


def write_directory_summary_to_workbook(count_sum, summary, directory_sheet):    
    directory_sheet.title = "目录页"

    # 首行 ,字段名称
    directory_sheet.cell(row=1, column=1, value="序号")
    directory_sheet.cell(row=1, column=2, value="文件夹名称")
    directory_sheet.cell(row=1, column=3, value="文件数量")
    # 第2行,总数量
    directory_sheet.cell(row=2, column=1, value=0)
    directory_sheet.cell(row=2, column=2, value="文件总数量")
    directory_sheet.cell(row=2, column=3, value=count_sum)
    # 第3行 开始,每个文件夹内的文件数量
    for i, (folder_name, file_count) in zip(itertools.count(start=3), summary):
        directory_sheet.cell(row=i, column=1, value=i - 2)
        directory_sheet.cell(row=i, column=2, value=folder_name)
        directory_sheet.cell(row=i, column=3, value=file_count)


def write_files_in_directory_to_workbook(folder_name, workbook, sheet_name):   
    file_list = os.listdir(folder_name)
    sheet = workbook.create_sheet(sheet_name)

    # 首行 ,字段名称
    sheet.cell(row=1, column=1, value="文件夹名称")
    sheet.cell(row=1, column=2, value="文件名")
    sheet.cell(row=1, column=3, value="类型")

    for i, filename in zip(itertools.count(start=2), file_list):
        file_path = os.path.join(folder_name, filename)
        sheet.cell(row=i, column=1, value=folder_name)
        sheet.cell(row=i, column=2, value=filename)

        # 判定文件 和 文件夹
        if os.path.isfile(file_path):
            # 获取文件后缀名
            file_extension = os.path.splitext(filename)[1][1:]
            sheet.cell(row=i, column=3, value=file_extension)
        elif os.path.isdir(file_path):
            sheet.cell(row=i, column=3, value="文件夹")


def generate_file_summary(root_dir, workbook):
    summary = generate_directory_summary(root_dir)
    count_sum = count_files_in_directory(root_dir)
    directory_sheet = workbook.active
    write_directory_summary_to_workbook(count_sum, summary, directory_sheet)

    for i, (folder_name, _) in enumerate(summary, start=1):
        write_files_in_directory_to_workbook(folder_name, workbook, str(i))


def setup_hyperlinks(workbook_path):
    wb = openpyxl.load_workbook(workbook_path)
    sheet_names = set(wb.sheetnames)
    sheet1 = wb['目录页']

    # 创建一个蓝色字体样式,带下划线
    blue_font = Font(color="0000FF", underline="single")
    max_row = sheet1.max_row
    for rowNum in range(2, max_row + 1):
        num = sheet1.cell(row=rowNum, column=1).value
        if str(num) in sheet_names:
            cell = sheet1.cell(row=rowNum, column=1)
            cell.hyperlink = f"#{num}!A1"
            cell.font = blue_font

    wb.save(workbook_path)
    wb.close()


def main():
    root_dir = r"C:\Program Files"    # 参数1  统计的目录
    summary_filename = r"D:\文件统计表.xlsx"   # 参数2   最终保存的表格路径及名称
    workbook = openpyxl.Workbook()
    start_time = time.time()  # 代码运行计时开始

    # 用常规的try - finally块来确保文件被正确关闭
    try:
        generate_file_summary(root_dir, workbook)
        workbook.save(summary_filename)
        setup_hyperlinks(summary_filename)
    finally:
        workbook.close()

    end_time = time.time() - start_time  # 计算代码执行时间(单位为秒)

    # 将执行时间转换为时、分、秒的格式
    hours = int(end_time // 3600)
    minutes = int((end_time % 3600) // 60)
    seconds = float(end_time % 60)
    formatted_time = f"{hours:02d}:{minutes:02d}:{seconds:00.2f}"
    print("代码执行时间:", formatted_time)


if __name__ == "__main__":
    main()

再次看一下运行的效果,这次 统计 “C:\Program Files” 目录下的文件数,测试一下效率,运行时间如下图:
对比
同样统计这个目录,第二版代码的运行时间为59.51秒(没有超链接那步骤),第一版代码用时为 1分26.78秒 。第二版代码效率提高了一些。
开启超链接步骤,用时为 2分10.56秒,我测试的 **“C:\Program Files”**路径,文件夹太多了,超链接时间较长。

最终的表格效果,如下图:
最终效果

第二版代码 增加了 首行的字段,分表增加了 “类型” 列,方便分类筛选,目录页增加 超链接。

4 后记

通过以上代码,可以实现 统计文件数量的功能,并且有每层文件夹的详细列表,目录页还设置了超链接可以链接到分页表,方便管理和归档。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

da-peng-song

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值