Vergleichen Sie Verzeichnisse, aber nicht den Inhalt von Dateien

21

Mit diff -r kann ich diese Aufgabe erledigen, allerdings dauert es so lange, da diff den Inhalt der Datei überprüft.

Ich möchte etwas, das feststellt, dass zwei Dateien in Bezug auf ihre Größe identisch sind, zuletzt geändert wurden usw. Aber keine Prüfung der Datei nach und nach (zum Beispiel dauert ein Video so lange)

Gibt es einen anderen Weg?

eez0
quelle

Antworten:

20

Standardmäßig vergleicht rsync nur Dateimetadaten.

rsync -n -a -i --delete source/ target/

Erläuterung:

  • -n nicht kopieren oder löschen <- DAS IST WICHTIG !! 1
  • -a Vergleichen Sie alle Metadaten der Datei wie Zeitstempel und Attribute
  • -i Eine Informationszeile pro Datei drucken
  • --delete Melden Sie auch Dateien, die sich nicht in der Quelle befinden

Hinweis: Es ist wichtig, die Verzeichnisnamen mit einem Schrägstrich zu versehen. das ist eine rsync sache.

Wenn Sie auch Zeilen für identische Dateien anzeigen möchten, geben Sie diese -izweimal ein

rsync -n -a -ii --delete source/ target/

Beispielausgabe:

*deleting   removedfile   (file in target but not in source)
.d..t...... ./            (directory with different timestamp)
>f.st...... modifiedfile  (file with different size and timestamp)
>f+++++++++ newfile       (file in source but not in target)
.f          samefile      (file that has same metadata. only with -ii)

Denken Sie daran, dass rsync nur Metadaten vergleicht. Das heißt, wenn sich der Dateiinhalt geändert hat, die Metadaten jedoch gleich geblieben sind, meldet rsync, dass die Datei identisch ist. Dies ist ein unwahrscheinliches Szenario. Vertrauen Sie also entweder darauf, dass bei gleichen Metadaten die Daten identisch sind, oder vergleichen Sie die Dateidaten nach und nach.

Bonus: Informationen zum Fortschritt finden Sie hier: Schätzen Sie die verbleibende Zeit oder Arbeit, um rsync zu beenden?

Lesmana
quelle
1
Die Schrägstriche in source/und target/sind auch beide sehr wichtig! (Ohne sie werden Quell- und Zielverzeichnisnamen zusammen mit den
untergeordneten
Ich wünschte, ich hätte Ihren Kommentar früher gelesen, das ist so wichtig! Ich habe den Schrägstrich nur in der Quelle weggelassen und mich gefragt, warum die Dateien im Ziel nicht als angezeigt wurden *deleting, sondern nur die Dateien, die sich in der Quelle befinden. Die Schrägstriche können leicht versehentlich vergessen werden, und Sie erhalten eine plausible, aber falsche Ausgabe.
user643011
3

Verwenden Sie die -q( --brief) Option mit diff -r( diff -qr). Von der infoSeite für GNU diff:

1.6 Zusammenfassen, welche Dateien unterschiedlich sind

Wenn Sie nur herausfinden möchten, ob Dateien unterschiedlich sind und die Unterschiede nicht wichtig sind, können Sie das Ausgabeformat für die Zusammenfassung verwenden. In diesem Format diff' simply reports whether files differ. Thewählt die Option --brief '(`-q') dieses Ausgabeformat aus , anstatt die Unterschiede zwischen den Dateien anzuzeigen.

Dieses Format ist besonders nützlich, wenn Sie den Inhalt zweier Verzeichnisse vergleichen. Es ist auch viel schneller als die normalen zeilenweisen Vergleiche, da `diff 'die Analyse der Dateien stoppen kann, sobald es feststellt, dass es Unterschiede gibt.

Dies vergleicht nicht Zeile für Zeile, sondern die Datei als Ganzes, was den Prozessor erheblich beschleunigt (wonach Sie suchen).

laebshade
quelle
1
Das Problem von - q ist, dass der Vergleich normal ist und wenn ein Unterschied festgestellt wird, er stoppt (wenn es sich um den normalen Modus handelt, wird er immer wieder verglichen).
eez0
2

Hier ist ein schnelles Python-Skript, mit dem überprüft wird, ob Dateinamen, Uhrzeiten und Dateigrößen identisch sind:

import os
import sys

def getStats(path):
    for pathname, dirnames, filenames in os.walk(path):
        for filename in ( os.path.join(pathname, x) for x in filenames ):
            stat = os.stat(filename)
            yield filename[len(path):], stat.st_mtime, stat.st_size

sys.exit(tuple(getStats(sys.argv[1])) != tuple(getStats(sys.argv[2])))
Chris Down
quelle
1

Wenn Sie nur wissen müssen, ob Dateien aus zwei Dateisystemzweigen unterschiedlich sind (ohne einen Blick in Dateien zu werfen), können Sie Folgendes tun:

find /opt/branch1 -type f | sort | xargs -i md5sum {} >/tmp/branch1;
find /opt/branch2 -type f | sort | xargs -i md5sum {} >/tmp/branch2;
diff /tmp/branch1 /tmp/branch2;

HTH

Chaky
quelle
0

Basierend auf Chris Downs Drehbuch ist dieses Drehbuch etwas "visueller". Wenn Sie es mit zwei Argumenten folder1und folder2aufrufen, durchsucht es den ersten Ordner und durchsucht für jede Datei eine entsprechende Datei im zweiten Ordner. Wenn es gefunden wird, wird der relative Pfad in Grün gedruckt, wenn sie eine andere Änderungszeit oder -größe haben, wird es in Gelb gedruckt, und wenn es nicht gefunden wird, wird es in Rot gedruckt.

#!/usr/bin/env python

import os
import sys
from termcolor import colored

def compare_filestats(file1,file2):
    """
    Compares modified time and size between two files.
    Return:
        -1 if file1 or file2 does not exist
         0 if they exist and compare equal
         1 if they have different modified time, but same size
         2 if they have different size, but same modified time
         3 if they have different size, and different modified time
    """

    if not os.path.exists(file1) or not os.path.exists(file2):
        return -1

    stat1 = os.stat(file1)
    stat2 = os.stat(file2)

    return (stat1.st_mtime != stat2.st_mtime) \
        + 2*(stat1.st_size != stat2.st_size)

def compare_folders(folder1,folder2):
    """
    folder1: serves as reference and will be walked through
    folder2: serves as target and will be querried for each file in folder1

    Prints colored status for each file in folder1:
        missing: file was not found in folder2 
        mtime  : modified time is different
        size   : filesize is different
        ok     : found with same filestats
    """
    for dirpath, dirnames, filenames in os.walk(folder1):
        for file1 in ( os.path.join(dirpath, x) for x in filenames ):
            relpath = file1[len(folder1):]
            file2 = os.path.join( folder2, relpath )
            comp = compare_filestats(file1,file2)

            if comp < 0:
                status = colored('[missing]','red')
            elif comp == 1:
                status = colored('[mtime  ]','yellow')
            elif comp >= 2:
                status = colored('[size   ]','yellow')
            else:
                status = colored('[ok     ]','green')

            print status, relpath

if __name__ == '__main__':
    compare_folders(sys.argv[1],sys.argv[2])

Beachten Sie, dass dies nicht ausreicht, um zu entscheiden, ob die beiden Ordner identisch sind. Sie müssen es in beide Richtungen ausführen, um sicherzustellen, dass die beiden Ordner identisch sind. In der Praxis ist Chris 'Skript besser, wenn Sie nur wissen möchten, ob die Ordner identisch sind. Wenn Sie wissen möchten, was in einem Ordner fehlt oder was sich von einem Ordner zum anderen unterscheidet , werden Sie von meinem Skript darüber informiert .

HINWEIS: Sie müssen termcolor installiert haben pip install termcolor.

Sheljohn
quelle
0

Wenn Sie nur eine Struktur und einige grundlegende Informationen zu Dateien vergleichen möchten, können Sie Folgendes versuchen:

diff <(cd $DIR1 && ls -laR) <(cd $DIR2 && ls -laR)

Ich habe es nicht getestet, daher sind Änderungen willkommen :)

Volodymyr
quelle
2
Dies funktioniert nicht, da die Verzeichnisnamen selbst ebenfalls in den Ergebnissen enthalten sind.
Chris Down
Was ist, wenn wir die erste Spalte mit den Verzeichnisnamen ausschließen? like <(ls -laR | awk '{$ 1 = ""; print}')
Volodymyr
Nicht alle Zeilen sind Verzeichnisnamen, daher funktioniert das nicht richtig.
Chris Down
Nutzen Sie die Tatsache, dass jeder <()seine eigene Umgebung hat. Bearbeitet
ein