[python]查找文件夹重复文件脚本
功能特点
递归扫描所有子文件夹
找出内容相同的文件(即使文件名不同)
特别找出文件名相同但内容不同的文件
使用MD5哈希值确保准确性
处理文件访问异常,避免程序因权限问题而中断
清晰输出两种类型的重复文件信息
输出说明
脚本会输出两种类型的重复文件:
内容重复的文件:这些文件的内容完全相同(MD5哈希相同),无论文件名是否相同
同名但内容不同的文件:这些文件有相同的文件名但内容不同(MD5哈希不同)
注意事项
对于非常大的文件,计算哈希值可能需要一些时间
程序会跳过无法访问的文件(如权限不足的文件)
结果中只显示有重复的文件组,单独的文件不会显示
这个脚本特别适合您提到的场景,即有些文件名相同但大小/内容不同的文件也需要被识别出来。
import os
import hashlib
from collections import defaultdict
def get_file_hash(file_path, chunk_size=8192):
"""计算文件的MD5哈希值"""
hash_md5 = hashlib.md5()
try:
with open(file_path, "rb") as f:
for chunk in iter(lambda: f.read(chunk_size), b""):
hash_md5.update(chunk)
return hash_md5.hexdigest()
except (IOError, OSError):
return None
def find_duplicate_files(start_path):
"""查找重复文件"""
# 存储文件哈希值和路径的映射
hash_map = defaultdict(list)
# 存储文件名和路径的映射(用于找出同名但内容不同的文件)
name_map = defaultdict(list)
# 遍历所有文件
for root, dirs, files in os.walk(start_path):
for filename in files:
file_path = os.path.join(root, filename)
try:
# 记录文件名
name_map[filename].append(file_path)
# 计算文件哈希
file_hash = get_file_hash(file_path)
if file_hash:
hash_map[file_hash].append(file_path)
except (OSError, IOError):
continue
# 找出内容重复的文件
content_duplicates = {hash_val: paths for hash_val, paths in hash_map.items() if len(paths) > 1}
# 找出同名但可能内容不同的文件
name_duplicates = {name: paths for name, paths in name_map.items() if len(paths) > 1}
# 找出同名且内容不同的文件
same_name_diff_content = {}
for name, paths in name_duplicates.items():
# 获取这些文件的哈希值
hashes = {}
for path in paths:
file_hash = get_file_hash(path)
if file_hash:
if file_hash not in hashes:
hashes[file_hash] = []
hashes[file_hash].append(path)
# 如果有多个不同的哈希值,说明同名但内容不同
if len(hashes) > 1:
same_name_diff_content[name] = hashes
return content_duplicates, same_name_diff_content
def main():
current_dir = os.getcwd()
print(f"正在扫描目录: {current_dir}")
content_duplicates, same_name_diff_content = find_duplicate_files(current_dir)
if not content_duplicates and not same_name_diff_content:
print("没有找到重复文件。")
return
# 输出内容重复的文件
if content_duplicates:
print("\n找到以下内容重复的文件:")
for i, (file_hash, files) in enumerate(content_duplicates.items(), 1):
print(f"\n组 {i} (哈希: {file_hash}):")
for file_path in files:
print(f" - {file_path}")
print(f"\n总共找到了 {len(content_duplicates)} 组内容重复的文件。")
# 输出同名但内容不同的文件
if same_name_diff_content:
print("\n找到以下同名但内容不同的文件:")
for i, (filename, hash_groups) in enumerate(same_name_diff_content.items(), 1):
print(f"\n文件名: {filename}")
for j, (file_hash, files) in enumerate(hash_groups.items(), 1):
print(f" 变体 {j} (哈希: {file_hash}):")
for file_path in files:
print(f" - {file_path}")
print(f"\n总共找到了 {len(same_name_diff_content)} 个同名但内容不同的文件。")
if __name__ == "__main__":
main()