MD5 哈希查找重复文件

363 阅读3分钟

如何通过 MD5 哈希算法找到目录中的重复文件?

2、解决方案

方法一:使用哈希表

使用哈希表可以轻松地查找重复文件。以下是步骤:

  1. 使用 collections.defaultdict 创建一个哈希表,其中键是文件哈希值,值是文件名列表。
  2. 遍历目录中的每个文件,并计算其哈希值。
  3. 将哈希值和文件名添加到哈希表中。如果哈希值已经存在,则将文件名添加到文件名列表中。
  4. 遍历哈希表,并查找哈希值列表长度大于 1 的键。这些键对应于重复文件。

方法二:使用大小预过滤

该方法首先按相同大小对文件进行分组,然后对每个组中的文件计算 MD5 哈希值。这样可以减少 MD5 计算次数,提高效率。

以下是步骤:

  1. 遍历目录中的每个文件,并根据文件大小对文件进行分组。
  2. 对每个组中的文件计算 MD5 哈希值。
  3. 将哈希值和文件名添加到哈希表中。如果哈希值已经存在,则将文件名添加到文件名列表中。
  4. 遍历哈希表,并查找哈希值列表长度大于 1 的键。这些键对应于重复文件。

代码示例(方法一):

from collections import defaultdict
import hashlib
import os

def find_duplicate_files(directory):
  # 创建一个哈希表,其中键是文件哈希值,值是文件名列表
  hash_table = defaultdict(list)

  # 遍历目录中的每个文件
  for root, dirs, files in os.walk(directory):
    for file in files:
      # 计算文件的 MD5 哈希值
      file_path = os.path.join(root, file)
      hash_value = hashlib.md5(open(file_path, 'rb').read()).hexdigest()

      # 将哈希值和文件名添加到哈希表中
      hash_table[hash_value].append(file_path)

  # 遍历哈希表,并查找哈希值列表长度大于 1 的键
  duplicate_files = []
  for hash_value, file_paths in hash_table.items():
    if len(file_paths) > 1:
      duplicate_files.append(file_paths)

  return duplicate_files

# 打印重复文件
for duplicate_file in find_duplicate_files('/Users/bubble/Desktop/aF'):
  print('Duplicate files:')
  for file_path in duplicate_file:
    print(file_path)

代码示例(方法二):

from collections import defaultdict
import hashlib
import os

def find_duplicate_files(directory):
  # 创建一个哈希表,其中键是文件大小,值是文件名列表
  size_map = defaultdict(list)

  # 遍历目录中的每个文件
  for root, dirs, files in os.walk(directory):
    for file in files:
      # 计算文件的大小
      file_path = os.path.join(root, file)
      file_size = os.path.getsize(file_path)

      # 将文件大小和文件名添加到哈希表中
      size_map[file_size].append(file_path)

  # 遍历哈希表,并查找哈希值列表长度大于 1 的键
  duplicate_files = []
  for file_size, file_paths in size_map.items():
    if len(file_paths) > 1:
      # 计算文件哈希值
      hash_table = defaultdict(list)
      for file_path in file_paths:
        hash_value = hashlib.md5(open(file_path, 'rb').read()).hexdigest()
        hash_table[hash_value].append(file_path)

      # 遍历哈希表,并查找哈希值列表长度大于 1 的键
      for hash_value, file_paths in hash_table.items():
        if len(file_paths) > 1:
          duplicate_files.append(file_paths)

  return duplicate_files

# 打印重复文件
for duplicate_file in find_duplicate_files('/Users/bubble/Desktop/aF'):
  print('Duplicate files:')
  for file_path in duplicate_file:
    print(file_path)