6 Stimmen

Die Erkennung von doppelten Dateien

Ich möchte doppelte Dateien in einem Verzeichnisbaum erkennen. Wenn zwei identische Dateien gefunden werden, wird nur eines der Duplikate erhalten und die verbleibenden Duplikate werden gelöscht, um Speicherplatz zu sparen.

Doppelte Dateien sind Dateien mit demselben Inhalt, die sich in Dateinamen und Pfad unterscheiden können.

Ich habe daran gedacht, Hash-Algorithmen für diesen Zweck zu verwenden, aber es besteht die Möglichkeit, dass verschiedene Dateien dieselben Hashes haben. Daher benötige ich einen zusätzlichen Mechanismus, der mir mitteilt, dass die Dateien nicht gleich sind, auch wenn die Hashes gleich sind, da ich nicht zwei verschiedene Dateien löschen möchte.

Welchen zusätzlichen schnellen und zuverlässigen Mechanismus würden Sie verwenden?

1 Stimmen

Die Wahrscheinlichkeit einer Hash-Kollision ist äußerst gering. Wenn Sie 100%ige Sicherheit darüber hinaus wünschen, können Sie einfach die vollständigen Dateiinhalte vergleichen - die Leistung ist selten so wichtig.

1 Stimmen

@delnan: Das ist nicht korrekt. Die Wahrscheinlichkeit einer Kollision für eine bestimmte Datei ist gering, für große Dateisammlungen ist sie jedoch viel höher - siehe das Geburtstagsparadoxon als Beispiel. Die Wahrscheinlichkeit, dass zwei Personen von insgesamt 23 am selben Tag Geburtstag haben, beträgt 50%. Die Wahrscheinlichkeit einer Kollision nimmt exponentiell zu, je größer die Sammlung wird.

1 Stimmen

@amit Ich kenne das Geburtstagsparadoxon, deshalb sage ich nicht "die Chancen sind so gering, dass es nicht notwendig ist, zu überprüfen". Auch mein Bauchgefühl sagt mir, dass die Chancen für zwei Dateien so gering sind, dass es hunderte oder tausende von Dateien brauchen würde, um Kollisionschancen >1 zu haben. Aber ja, ich sollte das lieber zuerst überprüfen. Die Tabelle in diesem Artikel (bezüglich Geburtstagsangriff) scheint das zu bestätigen. Wenn ich das richtig lese, erfordert ein perfekter 64-Bit-Hash 1,9 × 10^8 (= 190 Millionen) Dateien selbst für eine Kollisionschance von 0,1%.

0voto

Marley.Fi Punkte 1
/// ------------------------------------------------------------------------------------------------------------------------
    /// 
    /// Schreibt Duplikatdateien in eine List
    /// 
    private void CompareDirectory(string[] files)
    {
        for (int i = 0; i < files.Length; i++)
        {
            FileInfo one = new FileInfo(files[i]); // Hier könnte ein Fortschrittsbalken oder ähnliches stehen

            for (int i2 = 0; i2 < files.Length; i2++) 
            {
                if (i != i2 && !duplicatePathsOne.Contains(files[i2])) // Um doppelte Einträge zu verhindern
                {
                    FileInfo two = new FileInfo(files[i2]);
                    if (FilesAreEqual_OneByte(one, two))
                    {
                        duplicatePathsOne.Add(files[i]);
                        duplicateNamesOne.Add(Path.GetFileName(files[i]));
                        duplicatePathsTwo.Add(files[i2]);
                        duplicateNamesTwo.Add(Path.GetFileName(files[i2]);
                    }
                }
            }
        }
    }

/// ------------------------------------------------------------------------------------------------------------------------
    /// 
    /// Vergleicht Dateien binär
    /// 
    private static bool FilesAreEqual_OneByte(FileInfo first, FileInfo second)
    {
        if (first.Length != second.Length)
            return false;

        using (FileStream fs1 = first.OpenRead())
        using (FileStream fs2 = second.OpenRead())
        {
            for (int i = 0; i < first.Length; i++)
            {
                if (fs1.ReadByte() != fs2.ReadByte())
                    return false;
            }
        }

        return true;
    }

0voto

Igor Krupitsky Punkte 707

Hier ist ein VBS-Skript, das eine CSV-Datei generiert, um doppelte Dateien in einem Ordner anhand des Dateinamens und der Größe anzuzeigen.

Set fso = CreateObject("Scripting.FileSystemObject")
Dim dic: Set dic = CreateObject("Scripting.Dictionary")
Dim oLog 'As Scripting.TextStream

Set oArgs = WScript.Arguments

If oArgs.Count = 1 Then
    sFolderPath = GetFolderPath()
    Set oLog = fso.CreateTextFile(sFolderPath & "\DublicateFiles.csv", True)
    oLog.Write "sep=" & vbTab & vbCrLf
    CheckFolder oArgs(I)
    oLog.Close
    Msgbox "Erledigt!"
Else
    Msgbox "Ordner abwerfen"
End If

Sub CheckFolder(sFolderPath)
    Dim sKey
    Dim oFolder 'As Scripting.Folder
    Set oFolder = fso.GetFolder(sFolderPath)

    For Each oFile In oFolder.Files
        sKey = oFile.Name & " - " & oFile.Size

        If dic.Exists(sKey) = False Then 
            dic.Add sKey, oFile.Path
        Else
            oLog.Write oFile.Path & vbTab & dic(sKey) & vbCrLf
        End If
    Next

    For Each oChildFolder In oFolder.SubFolders
        CheckFolder oChildFolder.Path
    Next
End Sub

Function GetFolderPath()
    Dim oFile 'As Scripting.File
    Set oFile = fso.GetFile(WScript.ScriptFullName)
    GetFolderPath = oFile.ParentFolder
End Function

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X