43 Stimmen

Rekursiv vergleichen Sie zwei Verzeichnisse, um sicherzustellen, dass sie dieselben Dateien und Unterverzeichnisse haben

Von dem, was ich beobachte, ist filecmp.dircmp rekursiv, aber unzureichend für meine Bedürfnisse, zumindest in py2. Ich möchte zwei Verzeichnisse und alle enthaltenen Dateien vergleichen. Existiert das, oder muss ich es aufbauen (zum Beispiel mit os.walk). Ich bevorzuge vorgefertigte Lösungen, bei denen bereits jemand anderes das Einheitstesten durchgeführt hat :)

Der tatsächliche 'Vergleich' kann nachlässig sein (zum Beispiel Berechtigungen ignorieren), wenn das hilft.

Ich hätte gerne etwas Boolesches, und report_full_closure ist ein gedruckter Bericht. Es geht auch nur in gemeinsame Unterverzeichnisse. AFIAC, wenn sie etwas im linken oder rechten Verzeichnis haben, sind nur diese unterschiedlichen Verzeichnisse. Ich baue dies stattdessen mit os.walk.

0 Stimmen

Was ist "AFIAC"? Kann es nicht in einem gängigen Akronym finden, wenn gesucht wird.

0 Stimmen

@LondonAppDev Meine Vermutung ist, dass der Autor AFAIC gemeint hat (so weit ich das beurteilen kann (z.B. oxfordlearnersdictionaries.com/us/definition/english/…)), aber es möglicherweise als AFIAC falsch geschrieben hat. Eng verwandt mit AFAIK, d.h. so weit ich weiß.

3voto

Raullen Chai Punkte 195

Eine weitere Lösung besteht darin, das Layout von dir1 und dir2 zu vergleichen und den Inhalt der Dateien zu ignorieren

Siehe Gist hier: https://gist.github.com/4164344

Bearbeiten: Hier ist der Code, falls der Gist aus irgendeinem Grund verloren geht:

import os

def compare_dir_layout(dir1, dir2):
    def _compare_dir_layout(dir1, dir2):
        for (dirpath, dirnames, filenames) in os.walk(dir1):
            for filename in filenames:
                relative_path = dirpath.replace(dir1, "")
                if os.path.exists( dir2 + relative_path + '\\' +  filename) == False:
                    print relative_path, filename
        return

    print 'Dateien in "' + dir1 + '" aber nicht in "' + dir2 +'"'
    _compare_dir_layout(dir1, dir2)
    print 'Dateien in "' + dir2 + '" aber nicht in "' + dir1 +'"'
    _compare_dir_layout(dir2, dir1)

compare_dir_layout('xxx', 'yyy')

3voto

oats Punkte 76

Diese rekursive Funktion scheint für mich zu funktionieren:

def has_differences(dcmp):
    differences = dcmp.left_only + dcmp.right_only + dcmp.diff_files
    if differences:
        return True
    return any([has_differences(subdcmp) for subdcmp in dcmp.subdirs.values()])

Angenommen, ich habe nichts übersehen, könnten Sie einfach das Ergebnis negieren, wenn Sie wissen wollen, ob die Verzeichnisse gleich sind:

from filecmp import dircmp

comparison = dircmp("dir1", "dir2")
same = not has_differences(comparison)

2voto

Brent Punkte 3741

Da du nur ein Ergebnis von Wahr oder Falsch haben möchtest, wenn du diff installiert hast:

def are_dir_trees_equal(dir1, dir2):
    process = Popen(["diff", "-r", dir1, dir2], stdout=PIPE)
    exit_code = process.wait()
    return not exit_code

0 Stimmen

Ein Problem, das ich damit habe, ist, dass es leider keine Möglichkeit gibt zu sagen "Stop, wenn Sie einen Unterschied gefunden haben". Das sollte es geben! Mit großen Verzeichnissen kann diff enorme Mengen an Zeit benötigen, um abgeschlossen zu werden, und in diesem Anwendungsfall unnötigerweise.

1voto

alzix Punkte 23

Basiert auf python problem 12932 und filecmp Dokumentation können Sie folgendes Beispiel verwenden:

import os
import filecmp

# Erzwinge Inhaltsvergleich anstelle von Vergleich nur von os.stat Attributen
filecmp.cmpfiles.__defaults__ = (False,)

def _is_same_helper(dircmp):
    assert not dircmp.funny_files
    if dircmp.left_only or dircmp.right_only or dircmp.diff_files or dircmp.funny_files:
        return False
    for sub_dircmp in dircmp.subdirs.values():
       if not _is_same_helper(sub_dircmp):
           return False
    return True

def is_same(dir1, dir2):
    """
    Vergleiche zwei Verzeichnisse rekursiv
    :param dir1: Pfad zum ersten Verzeichnis
    :param dir2: Pfad zum zweiten Verzeichnis
    :return: True, wenn Verzeichnisse identisch sind, ansonsten False
    """
    if not os.path.isdir(dir1) or not os.path.isdir(dir2):
        return False
    dircmp = filecmp.dircmp(dir1, dir2)
    return _is_same_helper(dircmp)

0voto

Gregg Lind Punkte 19744

Hier ist meine Lösung: Gist

def dirs_same_enough(dir1,dir2,report=False):
    '''Verwenden Sie os.walk und filecmp.cmpfiles, um zu
    bestimmen, ob zwei Verzeichnisse 'ausreichend gleich' sind.

    Argumente:
        dir1, dir2: zwei Verzeichnispfade
        report: wenn True, geben Sie das filecmp.dircmp(dir1,dir2).report_full_closure()
                aus, bevor Sie zurückkehren

    Gibt zurück:
        bool

    '''
    # os walk:  root, list(dirs), list(files)
    # Diese Listen haben keine konsistente Reihenfolge,
    # os.walk hat auch keine garantierte Reihenfolge, daher sortieren wir.
    walk1 = sorted(list(os.walk(dir1)))
    walk2 = sorted(list(os.walk(dir2)))

    def report_and_exit(report,bool_):
        if report:
            filecmp.dircmp(dir1,dir2).report_full_closure()
            return bool_
        else:
            return bool_

    if len(walk1) != len(walk2):
        return false_or_report(report)

    for (p1,d1,fl1),(p2,d2,fl2) in zip(walk1,walk2):
        d1,fl1, d2, fl2 = set(d1),set(fl1),set(d2),set(fl2)
        if d1 != d2 or fl1 != fl2:
            return report_and_exit(report,False)
        for f in fl1:
            same,diff,weird = filecmp.cmpfiles(p1,p2,fl1,shallow=False)
            if diff or weird:
                return report_and_exit(report,False)

    return report_and_exit(report,True)

0 Stimmen

false_or_report() ist nicht definiert.

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