用Python检测重复文件

3 投票
4 回答
3091 浏览
提问于 2025-04-19 05:32

我正在尝试用Python写一个脚本,目的是整理文件(比如照片和视频),检查每个文件的元数据,找到所有重复的文件并把它们移动到一个单独的文件夹里。不过在检查元数据的部分遇到了困难。我试过用os.stat这个方法,但它并不能正确判断重复的文件。理想情况下,我应该能做到类似这样的事情:

if os.stat("original.jpg")== os.stat("duplicate.jpg"):  
    shutil.copy("duplicate.jpg","C:\\Duplicate Folder") 

有没有人能给点建议?

4 个回答

0

os.stat 可以提供一些文件的基本信息,比如创建时间。不过,单靠这些信息来判断两个文件是否相同并不是个好办法。

举个例子:两个文件可能内容完全一样,但创建时间却不同。因此,光比较这些信息是没用的。Sylvain Leroux 提出的办法在性能和准确性上是最好的,因为不同的文件有相同哈希值的情况非常少见。

所以,除非你有大量的数据,并且重复的文件会导致系统崩溃,否则这个方法是最合适的。

如果你确实面临这种情况(但看起来并不是),那么唯一能让你100%确定两个文件相同的方法就是逐字节地进行比较。

0

如果两个文件的 md5 值相同,那它们就是完全一样的重复文件。

from hashlib import md5
with open(file1, "r") as original:
    original_md5 = md5(original.read()).hexdigest()
    with open(file2, "r") as duplicate:
       duplicate_md5 = md5(duplicate.read()).hexdigest()
       if original_md5 == duplicate_md5:
          do_stuff()

在你的例子中,你使用的是 jpg 文件,这种情况下你需要用 open 方法,并且它的第二个参数要设置为 rb。想了解更多,可以查看 open 的文档。

2

你可以做几件事情。你可以比较每个文件的内容或者它们的哈希值,或者你也可以查看一些从os.stat结果中选出的特定属性,比如:

def is_duplicate(file1, file2):
    stat1, stat2 = os.stat(file1), os.stat(file2)
    return stat1.st_size==stat2.st_size and stat1.st_mtime==stat2.st_mtime
2

这是一个基本的循环,用来利用一个set来记录已经遇到的文件:

import glob
import hashlib

uniq = set()
for fname in glob.glob('*.txt'):
    with open(fname,"rb") as f:
        sig = hashlib.sha256(f.read()).digest()
        if sig not in uniq:
            uniq.add(sig)
            print fname
        else:
            print fname, " (duplicate)"

需要注意的是,任何哈希函数都有可能出现一点点小问题,这叫做碰撞。也就是说,可能会有两个不同的文件产生相同的哈希值。根据你的需求,这种情况可能是可以接受的,也可能不可以。

根据Thomas Pornin在另一个回答中提到的

“比如说,使用SHA-256(n=256)和十亿条消息(p=109),那么发生碰撞的概率大约是4.3*10-60。”


根据你的需求,如果你需要检查其他属性来识别“真正的”重复文件,可以把sig = ....这一行改成适合你的内容。例如,如果你需要检查“内容相同”和“拥有者相同”(st_uid是通过os.stat()返回的),可以这样写:

    sig = ( hashlib.sha256(f.read()).digest(), 
            os.stat(fname).st_uid )

撰写回答