Verzeichnisbäume miteinander vergleichen

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
Spam&Eggs
User
Beiträge: 15
Registriert: Donnerstag 15. Februar 2018, 22:09

Puh, :P dass hat gedauert aber ich glaube jetzt hab ich es verstanden. :idea:
Der Fehler lag wohl in der get_filepaths Funktion. Ich glaube so ist es jetzt OK:

Code: Alles auswählen

def get_filepaths(verzeichnis):
    """Erzeuge eine Dateiliste mit allen Dateipfaden in dem übergebenen Verzeichnis"""

    dateiliste = []     # Liste, die alle Dateien im übergebenen Verzeichnis enthält.

    # Durchlaufe den Verzeichnisbaum:
    for root, directories, files in os.walk(verzeichnis):
        for filename in files:

            # Füge die beiden Strings für den kompletten Pfad zusammen:
            dateipfad = os.path.join(os.path.relpath(verzeichnis, root), filename)
            dateiliste.append(dateipfad)

    return dateiliste
als Ergebnis erhalte ich jetzt:

Code: Alles auswählen

{'../../file_neu.jpg', './file_A.jpg', '../file_neu.jpg'}
Das Ergebnis stimmt jetzt. Unschön ist noch, dass
1.Die in dir_A fehlenden Dateien unsortiert ausgegeben werden.
2. Die Pfade zu den fehlenden Dateien relativ ausgegeben werden.

zu 1. Das ist bei einem Set wohl nicht zu ändern.
zu 2. Bei relativ wenigen Änderungen ist das kein Problem. Bei großen, stark verzweigten Verzeichnissen mit vielen Änderungen kann das etwas unübersichtlich sein.

Mit beiden kleinen Schönheitsfehlern kann ich aber gut leben.

Nochmals herzlichen Dank an Alle für die Zeit, die ihr für mich aufgewendet habt. Ich habe auf jeden Fall einiges gelernt.
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@Spam&Eggs: zu 1) Verzeichnisse sind unsortiert, aber man kann ja nachträglich noch sortieren. zu 2) du benutzt relpath falsch, vergleiche nochmal mein Beispiel mit Deinem Code.
Spam&Eggs
User
Beiträge: 15
Registriert: Donnerstag 15. Februar 2018, 22:09

@sirius3: Ich hoffe in u. a. Version ist jetzt alles OK. Die Pfade werden nicht mehr relativ ausgegeben und es ist auch alles schön sortiert:

Code: Alles auswählen

# !/usr/local/bin/python3
# coding: utf-8


"""
Vergleiche den Inhalt von zwei Verzeichnisbäumen.
"""

import os


def main():
    """
    Framework für den Aufruf der Funktion, die die beiden Verzeichnisse vergleicht.
    """

    # Hole die Pfade zu den zu vergleichenden Verzeichnissen vom Nutzer
    dir_a = get_pathname(1)
    dir_b = get_pathname(2)

    # Generiere die Dateilisten:
    dateiliste_1 = get_filepaths(dir_a)
    dateiliste_2 = get_filepaths(dir_b)

    # Vergleiche die Dateilisten und gebe die Unterschiede aus:
    diff_set = set(dateiliste_2) - set(dateiliste_1)

    # Differenzset zum sortieren und zur Ausgabe in Liste umwandeln
    diff_liste = list(diff_set)
    print("\nDateien die im Originalverzeichnis fehlen:\n")
    diff_liste.sort()
    [print(element) for element in diff_liste]


def get_pathname(nr):
    """Hole den Pfad vom Nutzer"""

    while True:
        print("\nGebe den Pfad zum ", str(nr) + ".", "Verzeichnis ein:\n")
        pfad = input()

        # Prüfe, ob das eingegebene Verzeichnis existiert:
        if os.path.exists(pfad):
            return pfad
        else:
            print("Das Verzeichnis existiert nicht, versuche es noch "
                  "einmal.")


def get_filepaths(verzeichnis):
    """Erzeuge eine Dateiliste mit allen Dateipfaden in dem übergebenen Verzeichnis"""

    dateiliste = []     # Liste, die alle Dateien im übergebenen Verzeichnis enthält.

    # Durchlaufe den Verzeichnisbaum:
    for root, directories, files in os.walk(verzeichnis):
        for filename in files:
            # Füge die beiden Strings für den kompletten Pfad zusammen:
            dateipfad = os.path.join(os.path.relpath(root, verzeichnis), filename)
            dateiliste.append(dateipfad)
    return dateiliste


# Wenn der Code eigenständig laufen soll und nicht importiert werden soll, rufe die
# Funktion main() auf:
if __name__ == '__main__':
    main()
Hier ist die Ausgabe für meine Testumgebung:

Code: Alles auswählen

Dateien die im Originalverzeichnis fehlen:

./DSCN8221.JPG
./DSCN8222.JPG
A1/DSCN8219.JPG
A1/DSCN8220.JPG
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

Listcomprehensions sind nicht dazu da, for-Schleifen zu ersetzen. Eine Liste die nur aus None-Werten besteht und gleich nach dem Erzeugen weggeschmissen wird, ist Quatsch.

os.path.join und os.path.relpath würde ich noch vertauschen.
Spam&Eggs
User
Beiträge: 15
Registriert: Donnerstag 15. Februar 2018, 22:09

@Sirius3: Wo du recht hast, hast du recht. Ich habe deine Anregungen noch umgesetzt.
Antworten