Mit Python doppelte Dateien finden


Ewelina Fiebig


Duplicate umbrellas

Angenommen, Sie arbeiten an einem NLP-Projekt. Ihre Eingabedaten sind wahrscheinlich Dateien wie PDF, JPG, XML, TXT oder ähnliches und es gibt eine Menge davon. Es ist nicht ungewöhnlich, dass in großen Datenbeständen einige Dokumente mit unterschiedlichen Namen exakt den gleichen Inhalt haben, d.h. es handelt sich um Duplikate. Dafür kann es verschiedene Gründe geben. Der wohl häufigste ist die fehlerhafte Speicherung und Archivierung der Dokumente.

Unabhängig von der Ursache ist es wichtig, die Duplikate zu finden und aus dem Datensatz zu entfernen, bevor Sie mit dem Labeling der Dokumente beginnen.

In diesem Blogbeitrag werde ich kurz demonstrieren, wie der Inhalt verschiedener Dateien mit Hilfe des Python-Moduls filecmp verglichen werden kann. Nachdem die Duplikate identifiziert wurden, werde ich zeigen, wie sie automatisch gelöscht werden können.


Beispiel-Dokumente


Für den Zweck dieser Präsentation betrachten wir einen einfachen Datensatz, der sechs Dokumente enthält.

Hier eine Abbildung, die die Dokumente zeigt:

Wir sehen, dass die Dokumente "doc1.pdf", "doc4.pdf" und "doc5.pdf" genau den gleichen Inhalt haben. Dasselbe gilt für "doc2.jpg" und "doc6.jpg". Ziel ist es daher, die Duplikate "doc4.pdf", "doc5.pdf" und "doc6.jpg" zu identifizieren und zu entfernen.


Finden der Duplikate


Das Modul filecmp bietet dafür eine sehr schöne Funktion - filecmp.cmp(f1, f2, shallow=True) - an. Sie vergleicht die Dateien mit den Namen f1 und f2 und gibt True zurück, wenn sie identisch zu sein scheinen. Andernfalls gibt sie False zurück. Mit dem Parameter shallow kann der Benutzer angeben, ob der Vergleich auf den os.stat()-Signaturen der Dateien oder eher auf deren Inhalt basieren soll. Der Vergleich der Inhalte wird durch die Einstellung shallow=False sichergestellt.

Ein beispielhafter Python-Code zum Auffinden der Duplikate könnte daher so aussehen:

import os
from pathlib import Path
from filecmp import cmp


# list all documents
DATA_DIR = Path('/path/to/your/data/directory')
files = sorted(os.listdir(DATA_DIR))

# list containing the classes of documents with the same content
duplicates = []

# comparison of the documents
for file in files:
    
    is_duplicate = False
    
    for class_ in duplicates:
        is_duplicate = cmp(
            DATA_DIR / file,
            DATA_DIR / class_[0],
            shallow = False
        )
        if is_duplicate:
            class_.append(file)
            break
    
    if not is_duplicate:
        duplicates.append([file])     

# show results
duplicates

Ausgabe:

[['doc1.pdf', 'doc4.pdf', 'doc5.pdf'], ['doc2.jpg', 'doc6.jpg'], ['doc3.pdf']]

Die obige Ausgabe ist eine Liste, die die identifizierten "Äquivalenzklassen" enthält, d.h. Listen von Dokumenten mit gleichem Inhalt. Beachten Sie, dass es ausreicht, ein gegebenes Dokument mit nur einem Vertreter aus jeder Klasse zu vergleichen, z.B. dem ersten Vertreter class_[0].

Wir erfahren zum Beispiel, dass das Dokument "doc1.pdf" den gleichen Inhalt hat wie die Dokumente "doc4.pdf" und "doc5.pdf". Ausserdem hat das Dokument "doc2.jpg" den gleichen Inhalt wie "doc6.jpg" und das Dokument "doc3.pdf" hat keine Duplikate. All dies entspricht dem, was wir in der obigen Abbildung beobachtet haben.


Entfernen von Duplikaten


Der nächste Schritt bestünde darin, die Duplikate "doc4.pdf", "doc5.pdf" und "doc6.jpg" zu entfernen. Ein beispielhafter Python-Code, der diese Aufgabe erfüllt, könnte so aussehen:

# remove the duplicates
for class_ in duplicates:
    for file in class_[1:]:
        os.remove(DATA_DIR / file)

Es gibt sicherlich noch andere Möglichkeiten, den Code zu schreiben oder generell Dateien zu vergleichen. In diesem Artikel habe ich einfach eine der vielen Möglichkeiten aufgezeigt.

Ich möchte Sie auch ermutigen, sich das filecmp-Modul genauer anzusehen. Es bietet neben der filecmp.cmp()-Funktion auch andere Methoden wie filecmp.cmpfiles(), die zum Vergleich von Dateien in zwei Verzeichnissen verwendet werden können und somit Ihren Bedürfnissen noch besser entsprechen könnten.