Doppelte Dateien finden

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
sabram
User
Beiträge: 28
Registriert: Mittwoch 5. Januar 2011, 13:42

Ich verzweifel gerade irgendwie an einem kleinen Skript das eigentlich nicht allzuschwer seien sollte.

Ich versuche doppelte Dateien in einem Ordner bzw in den Unterordnern zu finden.

Code: Alles auswählen

    def showReport(self, event):
        files_hash = {}
        self.main(os.getcwd())
        print self.FileList
        for item in self.FileList:
            f = file(item,'rb')
            sum = md5.new(f.read())
            f.close()
            try:
                files_hash[sum.hexdigest()].append(item)
            except KeyError:
                files_hash[sum.hexdigest()] = [item]
        
        dupes = [values for values in files_hash.values() if len(values) > 1]
        print 'Identical files:'
        print dupes
        
    def main(self,path):
        for entry in os.listdir(path):
            if os.path.isdir(entry):
                self.main(os.path.join(path,entry))
            self.FileList.append(os.path.abspath(entry))
allerdinsg wirdt er mir momentan immer eine exception im showReports Teil das er eine datei die 'C:\\Users\\Sascha\\Downloads\\winexp - Kopie (2).exe' heißt z.B. nicht finden kann ( diese Exception tritt genau beim f = file(item,'rb') , der Pfad 'C:\\Users\\Sascha\\Downloads\\winexp - Kopie (2).exe' kommt natürlich aus der main ) aber der sollte doch korrekt sein oder irre ich mich da ?

Danke
Mfg sabram
BlackJack

@sabram: Bei Deinem `main()` erfindest Du im Grunde `os.walk()` noch einmal neu.

Die `main()` ist ausserdem im Grunde eine Funktion und keine Methode. Und der Name ist komisch!?

Dateien sollte man mit der ``with``-Anweisung und mit `open()` öffnen. Du liesst die Dateien immer komplett in den Speicher. Solltest hoffen, dass Du nie an einem DVD-Image vorbei kommst. ;-)

Für `files_hash` würde sich ein `collections.defaultdict` anbieten.

Und die Dateien in so einer Liste sind *vielleicht* identisch. Garantiert ist das nicht. Kommt also darauf an, mit wie viel Unsicherheit Du da leben kannst. Wenn man sicher sein will, muss man schon den Dateiinhalt vergleichen. Ein klein wenig sicherer bekommt man das, wenn man nicht nur die Prüfsumme als Schlüssel nimmt, sondern ein Tupel aus Prüfsumme und Dateilänge. 100%ig ist das dann natürlich auch noch nicht.
sabram
User
Beiträge: 28
Registriert: Mittwoch 5. Januar 2011, 13:42

@Blackjack:

Vielen Dank für die Antwort.
Die methodennamen bzw Funktionsnamen ( und doch es sind methoden :) ) werden noch angepasst sobald das gröbere Aussengerüst was ich mir vorstelle mal Gestalt annimmt.

Ich kann mit viel Unsicherheit leben was das angeht, es geht vorrangig erstmal nur um einen groben Vergleich der Dateien mit md5 hash, das reicht mir ohne weiteres ( theoretisch würde mir sogar dateiname reichen ).

Ich versteh noch nicht ganz wo der Vorteil der open() Variante liegt, diese wird doch auch komplett geladen. Und löst mein Problem der Exception nicht :(

edit: die os.walk ist aber wirklich hübsch, habe nun auch den Fehler identifizieren können. verstehe ihn nur nicht.

Code: Alles auswählen

for dirpath,dirnames,filenames in os.walk(os.getcwd())
    for files in filenames:
        print os.path.abspath(files)
würde dann einen Pfad ausgeben zu 'C:\Users\Sascha\Downloads\winexp - Kopie (2).exe' den es aber gar nicht gibt, da die Datei im Unterordner liegt. Daher dann auch die Exception. Nur warum tut er sowas?

Gruß Sascha
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Warum vergleichst du dann nicht die Dateinamen, wenn das ausreicht. Das sollte wesentlich schneller gehen. Der Vorteil in der von BlackJack genannten open-Variante liegt darin, dass die Datei auch in jedem Fall wieder geschlossen wird.

Zu deinem Problem: Du solltest dir die Dokumentation zu ``os.walk`` durchlesen, dort steht im zweiten Absatz beschrieben, wie du an den vollständigen Pfad kommst. ``files`` ist übrigens in doppelter hinsicht ein schlechter Name: zu einen sind es gar keine Dateien, sonder Dateinamen und zum anderen sind es nicht mehrer Dateinamen sondern nur einer.

Code: Alles auswählen

for filename in filenames:
macht auch irgendwie Sinn ;-)

Sebastian
Das Leben ist wie ein Tennisball.
Antworten