背景介绍
在日常工作中,我们经常会遇到需要整理本地文件或分析项目结构的场景:
– 想知道项目目录中代码文件(.py/.java)与资源文件(.png/.json)的占比
– 需要清理磁盘空间,找出占用空间最大的文件类型
– 需要统计文档目录中文本文件与表格文件的分布
手动统计这些信息既耗时又容易出错,因此开发一个自动化的文件类型统计工具非常有必要。本文将介绍如何用Python实现一个本地文件类型统计与可视化工具,支持递归扫描目录、生成文本报告和可视化图表。
思路分析
工具实现分为五个核心模块:
- 命令行参数解析: 使用
argparse获取用户指定的目标目录 - 目录递归遍历: 使用
os.walk遍历目录下所有文件(包括子目录) - 文件类型统计: 提取文件扩展名,统计每种类型的数量和总大小
- 文本报告生成: 格式化输出统计结果到控制台
- 可视化图表生成: 使用
matplotlib绘制饼图(数量占比)和柱状图(大小占比)
代码实现
环境准备
需要安装matplotlib库用于可视化:
pip install matplotlib
完整代码
import os
import argparse
import math
import matplotlib.pyplot as plt
def convert_size(size_bytes):
"""
将字节数转换为易读的单位(KB/MB/GB等)
Args:
size_bytes (int): 文件大小(字节)
Returns:
str: 格式化后的大小字符串(保留一位小数)
Example:
convert_size(1234567) → "1.2 MB"
"""
if size_bytes == 0:
return "0 B"
# 定义单位转换级别与对应标签
size_units = ['B', 'KB', 'MB', 'GB', 'TB']
# 计算对应的单位级别(取对数)
unit_index = math.floor(math.log(size_bytes, 1024))
# 避免超过最大单位(TB)
unit_index = min(unit_index, len(size_units)-1)
# 转换为对应单位的值并保留一位小数
converted_size = round(size_bytes / (1024 ** unit_index), 1)
return f"{converted_size} {size_units[unit_index]}"
def collect_stats(target_dir):
"""
递归扫描目录,统计文件类型信息
Args:
target_dir (str): 目标目录路径
Returns:
dict: 统计结果字典,包含:
- total_files: 总文件数
- total_size: 总大小(字节)
- type_stats: 每种类型的详细统计(数量、大小)
"""
# 初始化统计结果
stats = {
"total_files": 0,
"total_size": 0,
"type_stats": {}
}
# 递归遍历目录
for root, _, files in os.walk(target_dir):
for file_name in files:
# 获取文件完整路径
file_path = os.path.join(root, file_name)
try:
# 获取文件大小
file_size = os.path.getsize(file_path)
except (OSError, PermissionError):
# 跳过无法访问的文件
continue
# 更新总统计
stats["total_files"] +=1
stats["total_size"] += file_size
# 提取文件扩展名(统一转为小写)
_, ext = os.path.splitext(file_name)
ext = ext.lower()
# 处理无扩展名的文件
if not ext:
ext = "无扩展名"
else:
# 去掉扩展名前的点(如.py → py)
ext = ext[1:]
# 更新类型统计
if ext not in stats["type_stats"]:
stats["type_stats"][ext] = {"count":0, "size":0}
stats["type_stats"][ext]["count"] +=1
stats["type_stats"][ext]["size"] += file_size
return stats
def generate_text_report(stats, target_dir):
"""
生成控制台文本报告
Args:
stats (dict): collect_stats返回的统计结果
target_dir (str): 扫描目录路径
"""
print("\n=== 文件类型统计报告 ===")
print(f"扫描目录: {target_dir}")
print(f"总文件数: {stats['total_files']}")
print(f"总大小: {convert_size(stats['total_size'])}\n")
# 按文件数量降序排序
sorted_types = sorted(
stats["type_stats"].items(),
key=lambda x: -x[1]["count"]
)
print("按数量排序:")
for idx, (ext, data) in enumerate(sorted_types[:10], 1): # 显示前10种类型
count = data["count"]
size = data["size"]
# 计算占比
count_ratio = round(count / stats["total_files"] *100,1)
size_ratio = round(size / stats["total_size"] *100,1)
# 格式化输出
print(f"{idx}. .{ext} → {count}个({count_ratio}%), 总大小: {convert_size(size)}({size_ratio}%)")
# 处理剩余类型
if len(sorted_types) >10:
remaining_count = sum(x[1]["count"] for x in sorted_types[10:])
remaining_size = sum(x[1]["size"] for x in sorted_types[10:])
count_ratio = round(remaining_count / stats["total_files"] *100,1)
size_ratio = round(remaining_size / stats["total_size"] *100,1)
print(f"{11}. 其他 → {remaining_count}个({count_ratio}%), 总大小: {convert_size(remaining_size)}({size_ratio}%)")
def generate_visualization(stats, output_path="file_stats_charts.png"):
"""
生成可视化图表并保存
Args:
stats (dict): collect_stats返回的统计结果
output_path (str): 图表保存路径
"""
# 准备数据(取前5种类型+其他)
sorted_types = sorted(
stats["type_stats"].items(),
key=lambda x: -x[1]["count"]
)
top_types = sorted_types[:5]
others_count = sum(x[1]["count"] for x in sorted_types[5:])
others_size = sum(x[1]["size"] for x in sorted_types[5:])
# 添加"其他"类型(如果有)
if others_count >0:
top_types.append(("其他", {"count": others_count, "size": others_size}))
# 提取标签和数据
labels = [f".{ext}" if ext != "无扩展名" else "无扩展名" for ext, _ in top_types]
counts = [data["count"] for _, data in top_types]
sizes = [data["size"] for _, data in top_types]
# 计算大小占比
size_ratios = [round(s / stats["total_size"] *100,1) for s in sizes]
# 创建图表(1行2列)
fig, (ax1, ax2) = plt.subplots(1,2, figsize=(15,6))
# 左图: 数量占比饼图
ax1.pie(counts, labels=labels, autopct='%1.1f%%', startangle=90)
ax1.set_title("文件类型数量占比")
# 右图: 大小占比柱状图
bars = ax2.bar(labels, size_ratios, color='skyblue')
ax2.set_title("文件类型大小占比(%)")
ax2.set_xlabel("文件类型")
ax2.set_ylabel("占比(%)")
# 添加数值标签
for bar in bars:
height = bar.get_height()
ax2.text(bar.get_x() + bar.get_width()/2., height+0.5, f"{height}%", ha='center')
# 旋转x轴标签避免重叠
plt.setp(ax2.xaxis.get_majorticklabels(), rotation=45, ha='right')
# 调整布局并保存
plt.tight_layout()
plt.savefig(output_path, dpi=100)
plt.close()
print(f"\n统计完成!可视化图表已保存至: {output_path}")
def main():
"""
主函数: 解析参数→收集统计→生成报告→可视化
"""
# 解析命令行参数
parser = argparse.ArgumentParser(description="本地文件类型统计与可视化工具")
parser.add_argument(
"--dir",
default=os.getcwd(),
help="目标目录路径(默认: 当前目录)"
)
args = parser.parse_args()
# 验证目录有效性
if not os.path.isdir(args.dir):
print(f"错误: {args.dir}不是有效目录")
return
# 收集统计数据
print(f"正在扫描目录: {args.dir}...")
stats = collect_stats(args.dir)
if stats["total_files"] ==0:
print("未找到任何文件")
return
# 生成文本报告
generate_text_report(stats, args.dir)
# 生成可视化图表
generate_visualization(stats)
if __name__ == "__main__":
main()
使用说明
- 安装依赖:
pip install matplotlib - 运行工具:
- 扫描当前目录:
bash
python file_stats.py - 扫描指定目录:
bash
python file_stats.py --dir /path/to/your/directory
- 扫描当前目录:
- 输出结果:
- 控制台显示文本报告
- 生成
file_stats_charts.png图表文件
总结
本文实现的工具具有以下特点:
– 自动化: 递归扫描目录,无需手动干预
– 全面: 统计文件数量、大小及占比
– 直观: 同时提供文本报告和可视化图表
– 健壮: 处理无法访问的文件和权限问题
扩展方向:
– 支持过滤特定目录(如node_modules/.git)
– 导出CSV格式报告
– 添加文件大小排序选项
– 支持更多图表类型(如折线图、堆叠柱状图)
这个工具不仅能帮助我们快速了解文件分布,还可以作为Python文件操作、数据处理和可视化的学习案例。希望本文对你有所帮助!