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ß.

0voto

NotAUser Punkte 1396
def same(dir1, dir2):
"""Gibt True zurück, wenn rekursiv identisch, andernfalls False

"""
    c = filecmp.dircmp(dir1, dir2)
    if c.left_only or c.right_only or c.diff_files or c.funny_files:
        return False
    else:
        safe_so_far = True
        for i in c.common_dirs:
            same_so_far = same_so_far and same(os.path.join(frompath, i), os.path.join(topath, i))
            if not same_so_far:
                break
        return same_so_far

2 Stimmen

Wo hast du frompath und topath deklariert?

0voto

Rok Punkte 191

Dies überprüft, ob Dateien am selben Speicherort sind und ob ihr Inhalt identisch ist. Es wird nicht korrekt für leere Unterordner validieren.

import filecmp
import glob
import os

path_1 = '.'
path_2 = '.'

def folders_equal(f1, f2):
    file_pairs = list(zip(
        [x for x in glob.iglob(os.path.join(f1, '**'), recursive=True) if os.path.isfile(x)],
        [x for x in glob.iglob(os.path.join(f2, '**'), recursive=True) if os.path.isfile(x)]
    ))

    locations_equal = any([os.path.relpath(x, f1) == os.path.relpath(y, f2) for x, y in file_pairs])
    files_equal = all([filecmp.cmp(*x) for x in file_pairs]) 

    return locations_equal and files_equal

folders_equal(path_1, path_2)

0voto

Gh0sT Punkte 233

An alle, die nach einer einfachen Bibliothek suchen:

https://github.com/mitar/python-deep-dircmp

DeepDirCmp unterklasse im Grunde filecmp.dircmp und zeigt eine Ausgabe, die identisch zu diff -qr dir1 dir2 ist.

Verwendung:

from deep_dircmp import DeepDirCmp

cmp = DeepDirCmp(dir1, dir2)
if len(cmp.get_diff_files_recursive()) == 0:
    print("Verzeichnisse stimmen überein")
else:
    print("Verzeichnisse stimmen nicht überein")

0voto

AdamE Punkte 537

Basiert auf der aktuell akzeptierten Antwort von @Mateusz Kobos, stellt sich heraus, dass das zweite filecmp.cmpfiles mit shallow=False nicht notwendig ist, daher haben wir es entfernt. Man kann dirs_cmp.diff_files aus dem ersten dircmp erhalten. Ein häufiges Missverständnis (das auch wir hatten!) ist, dass dir_cmp nur oberflächlich ist und nicht die Dateiinhalte vergleicht! Es stellt sich heraus, dass das nicht stimmt! Die Bedeutung von shallow=True besteht nur darin, Zeit zu sparen und behandelt zwei Dateien mit unterschiedlichen letzten Änderungszeiten tatsächlich nicht als unterschiedlich. Wenn die letzte Änderungszeit zwischen zwei Dateien unterschiedlich ist, wird der Inhalt jeder Datei gelesen und deren Inhalt verglichen. Wenn die Inhalte identisch sind, ist es ein Treffer, auch wenn das letzte Änderungsdatum unterschiedlich ist! Wir haben hier detaillierte Ausgaben hinzugefügt, um mehr Klarheit zu schaffen. Sehen Sie sich anderswo (filecmp.cmp() ignoriert unterschiedliche os.stat()-Signaturen?) an, wenn Sie Unterschiede in st_modtime als Nichtübereinstimmung betrachten möchten. Wir haben auch auf die neuere pathlib- statt der os-Bibliothek umgestellt.

import filecmp
from pathlib import Path

def compare_directories_recursive(dir1:Path, dir2:Path,verbose=True):
"""
Vergleicht zwei Verzeichnisse rekursiv. 
Zuerst werden die Dateizahlen in jedem Verzeichnis verglichen. 
Zweitens werden Dateien als gleich angesehen, wenn ihre Namen, Größe und letztes Änderungsdatum gleich sind (auch bekannt als shallow=True in Python). 
Wenn sich das letzte Änderungsdatum unterscheidet, werden die Inhalte durch Lesen jeder Datei verglichen. 
Einschränkung: Wenn die Inhalte gleich sind und das letzte Änderungsdatum NICHT gleich ist, werden die Dateien immer noch als gleich betrachtet! 
Diese Einschränkung ist das Standardverhalten von Python filecmp, so unlogisch es auch erscheinen mag.

@param dir1: Pfad zum ersten Verzeichnis
@param dir2: Pfad zum zweiten Verzeichnis
"""

dirs_cmp = filecmp.dircmp(str(dir1), str(dir2))
if len(dirs_cmp.left_only)>0:
    if verbose:
        print(f"Es sollten nicht mehr Dateien im Originalverzeichnis als im Zielverzeichnis (left_only) sein: {dirs_cmp.left_only}")
    return False
if len(dirs_cmp.right_only)>0:
    if verbose:
        print(f"Es sollten nicht mehr Dateien im Zielverzeichnis als im Originalverzeichnis (right_only) sein: {dirs_cmp.right_only}")
    return False
if len(dirs_cmp.funny_files)>0:
    if verbose:
        print(f"Es sollten keine lustigen Dateien zwischen Original und Ziel geben. Diese Datei(en) sind lustig: {dirs_cmp.funny_files}")
    return False
if len(dirs_cmp.diff_files)>0:
    if verbose:
        print(f"Es sollten keine unterschiedlichen Dateien zwischen Original und Ziel geben. Diese Datei(en) sind unterschiedlich: {dirs_cmp.diff_files}")
    return False

for common_dir in dirs_cmp.common_dirs:
    new_dir1 = Path(dir1).joinpath(common_dir)
    new_dir2 = Path(dir2).joinpath(common_dir)
    if not compare_directories_recursive(new_dir1, new_dir2):
        return False
return True

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