Confronta le directory ma non il contenuto dei file


21

Con diff -r posso fare questo compito, tuttavia ci vuole molto tempo perché diff controlla il contenuto del file.

Voglio qualcosa che determini che due file sono uguali per quanto riguarda la loro dimensione, l'ultima modifica, ecc. Ma nessun controllo bit per bit del file (ad esempio un video impiega così tanto tempo)

C'è un altro modo?

Risposte:


20

rsync, per impostazione predefinita, confronta solo i metadati del file.

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

spiegazione:

  • -n in realtà non copiare o eliminare <- QUESTO È IMPORTANTE !! 1
  • -a confronta tutti i metadati di file come data e ora e attributi
  • -i stampa una riga di informazioni per file
  • --delete segnala anche i file che non sono nel sorgente

nota: è importante aggiungere i nomi di directory con una barra. questa è una cosa rsync.

se vuoi anche vedere le linee stampate per file identici, fornisci -idue volte

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

esempio di output:

*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)

ricorda che rsync confronta solo i metadati. ciò significa che se il contenuto del file è cambiato ma i metadati sono rimasti invariati, allora rsync segnalerà che il file è lo stesso. questo è uno scenario improbabile. quindi o confida che quando i metadati sono uguali i dati sono uguali, oppure devi confrontare i dati del file bit per bit.

bonus: per informazioni sullo stato vedi qui: Stimare il tempo o il lavoro rimasto per finire per rsync?


1
Le barre source/e target/sono anche molto importanti! (Senza di essi, confronterai i nomi delle directory di origine e di destinazione con i nomi dei file
secondari

Vorrei aver letto il tuo commento prima, questo è così importante! Ho omesso la barra solo nel sorgente e poi mi chiedevo perché i file nel target non fossero mostrati come *deleting, ma i file che erano nel sorgente sono stati mostrati. Le barre sono facili da dimenticare accidentalmente e quindi si ottiene un risultato plausibile ma sbagliato.
user643011

3

Utilizzare il -q( --briefopzionale) con diff -r( diff -qr). Dalla infopagina per GNU diff:

1.6 Riassumendo quali file differiscono

Quando vuoi solo scoprire se i file sono diversi e non ti importa quali siano le differenze, puoi utilizzare il formato di output di riepilogo. In questo formato, invece di mostrare le differenze tra i file, l' diff' simply reports whether files differ. Theopzione --brief '(`-q') seleziona questo formato di output.

Questo formato è particolarmente utile quando si confrontano i contenuti di due directory. È anche molto più veloce del normale confronto riga per riga, perché `diff 'può interrompere l'analisi dei file non appena sa che ci sono differenze.

Questo non confronterà riga per riga, ma piuttosto il file nel suo insieme, che accelera notevolmente il processore (cosa 'stai cercando).


1
Il problema di - q è che confronta normale e quando trova una differenza si ferma (se fosse la modalità normale continua a confrontare), quindi se i file enormi sono gli stessi durerà molto.
eez0,

2

Ecco un breve script in Python che verificherà che i nomi dei file, i mtimes e le dimensioni dei file siano tutti uguali:

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])))

1

Se hai solo bisogno di sapere se i file da due rami del file system sono diversi (senza guardare all'interno dei file) puoi fare qualcosa del genere:

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


0

Basato sulla sceneggiatura di Chris Down, questa sceneggiatura è un po 'più "visiva". Chiamandolo con due argomenti folder1e folder2, cammina la prima cartella e per ogni file cerca un file corrispondente nella seconda cartella. Se viene trovato, il relativo percorso viene stampato in verde, se hanno tempi o dimensioni modificati diversi, viene stampato in giallo e, se non viene trovato, viene stampato in rosso.

#!/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])

Si noti che questo non è sufficiente per decidere se le due cartelle sono uguali, è necessario eseguirlo in entrambi i modi per assicurarsi. In pratica, se vuoi solo sapere se le cartelle sono uguali , allora lo script di Chris è migliore. Se vuoi sapere cosa manca o è diverso da una cartella all'altra , allora il mio script ti dirà.

NOTA: è necessario termcolor installato, pip install termcolor.


0

Se desideri confrontare solo una struttura e alcune informazioni di base sui file, puoi provare qualcosa del genere:

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

Non l'ho provato, quindi tutte le modifiche sono benvenute :)


2
Questo non funzionerà poiché anche i nomi delle directory saranno presenti nei risultati.
Chris Down,

e se escludessimo la prima colonna con i nomi delle directory? come <(ls -laR | awk '{$ 1 = ""; print}')
Volodymyr,

Non tutte le righe sono nomi di directory, quindi non funzionerà correttamente.
Chris Down,

Approfitta del fatto che ognuno <()ha il suo ambiente. Modificato.
un CVn
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.