Crea al volo un file di archivio tar e reindirizzalo a md5sum
:
tar c dir | md5sum
Ciò produce un singolo valore hash MD5 che dovrebbe essere univoco per la configurazione del file e della sottodirectory. Nessun file viene creato su disco.
Se ti interessano solo i file e non le directory vuote, funziona bene:
find /path -type f | sort -u | xargs cat | md5sum
il suggerimento di ire_and_curses di usare tar c <dir>
presenta alcuni problemi:
- tar elabora le voci di directory nell'ordine in cui sono memorizzate nel filesystem e non c'è modo di cambiare quest'ordine. Questo effettivamente può produrre risultati completamente diversi se hai la "stessa" directory in posti diversi, e non conosco alcun modo per risolvere questo problema (tar non può "ordinare" i suoi file di input in un ordine particolare).
- Di solito mi interessa sapere se i numeri groupid e ownerid sono gli stessi, non necessariamente se la rappresentazione in stringa di group/owner è la stessa. Questo è in linea con ciò che per esempio
rsync -a --delete
fa:sincronizza praticamente tutto (meno xattrs e acls), ma sincronizzerà proprietario e gruppo in base al loro ID, non sulla rappresentazione di stringa. Quindi, se hai eseguito la sincronizzazione con un sistema diverso che non ha necessariamente gli stessi utenti/gruppi, dovresti aggiungere--numeric-owner
flag per tar - tar includerà il nome del file della directory che stai controllando, solo qualcosa di cui essere a conoscenza.
Finché non esiste una soluzione per il primo problema (o a meno che tu non sia sicuro che non ti riguardi), non utilizzerei questo approccio.
Il find
proposto anche le soluzioni basate su - non vanno bene perché includono solo file, non directory, il che diventa un problema se il checksum deve tenere a mente le directory vuote.
Infine, la maggior parte delle soluzioni suggerite non ordina in modo coerente, perché le regole di confronto potrebbero essere diverse tra i sistemi.
Questa è la soluzione che ho trovato:
dir=<mydir>; (find "$dir" -type f -exec md5sum {} +; find "$dir" -type d) | LC_ALL=C sort | md5sum
Note su questa soluzione:
- Il
LC_ALL=C
è garantire un ordinamento affidabile tra i sistemi - Questo non fa differenza tra una directory "named\nwithanewline" e due directory "named" e "withanewline", ma la possibilità che ciò accada sembra molto improbabile. Uno di solito risolve questo problema con un
-print0
flag perfind
, ma dal momento che ci sono altre cose da fare qui, posso solo vedere soluzioni che renderebbero il comando più complicato di quanto valga.
PS:uno dei miei sistemi utilizza un busybox limitato find
che non supporta -exec
né -print0
flags, e inoltre aggiunge '/' per indicare le directory, mentre findutils find non sembra, quindi per questa macchina devo eseguire:
dir=<mydir>; (find "$dir" -type f | while read f; do md5sum "$f"; done; find "$dir" -type d | sed 's#/$##') | LC_ALL=C sort | md5sum
Fortunatamente, non ho file/directory con newline nei loro nomi, quindi questo non è un problema su quel sistema.
find /path/to/dir/ -type f -name "*.py" -exec md5sum {} + | awk '{print $1}' | sort | md5sum
La trova Il comando elenca tutti i file che terminano con .py. Il valore hash MD5 viene calcolato per ogni file .py. AWK viene utilizzato per selezionare i valori hash MD5 (ignorando i nomi dei file, che potrebbero non essere univoci). I valori hash MD5 vengono ordinati. Viene quindi restituito il valore hash MD5 di questo elenco ordinato.
L'ho testato copiando una directory di test:
rsync -a ~/pybin/ ~/pybin2/
Ho rinominato alcuni file in ~/pybin2 .
Il find...md5sum
Il comando restituisce lo stesso output per entrambe le directory.
2bcf49a4d19ef9abd284311108d626f1 -
Per tenere conto del layout del file (percorsi), quindi il checksum cambia se un file viene rinominato o spostato, il comando può essere semplificato:
find /path/to/dir/ -type f -name "*.py" -exec md5sum {} + | md5sum
Su macOS con md5
:
find /path/to/dir/ -type f -name "*.py" -exec md5 {} + | md5