Il programma md5sum non fornisce checksum per le directory. Voglio ottenere un singolo checksum MD5 per l'intero contenuto di una directory, inclusi i file nelle sottodirectory. Cioè, un checksum combinato composto da tutti i file. C'è un modo per farlo?
Risposta accettata:
Il modo giusto dipende esattamente dal motivo per cui lo stai chiedendo:
Opzione 1:confronta solo i dati
Se hai solo bisogno di un hash del contenuto del file dell'albero, questo farà il trucco:
$ find -s somedir -type f -exec md5sum {} ; | md5sum
Questo prima riassume tutti i contenuti del file individualmente, in un ordine prevedibile, quindi passa quell'elenco di nomi di file e hash MD5 da sottoporre a hash, fornendo un unico valore che cambia solo quando cambia il contenuto di uno dei file nell'albero.
Sfortunatamente, find -s
funziona solo con BSD find(1), utilizzato in macOS, FreeBSD, NetBSD e OpenBSD. Per ottenere qualcosa di paragonabile su un sistema con GNU o SUS find(1), hai bisogno di qualcosa di un po' più brutto:
$ find somedir -type f -exec md5sum {} ; | sort -k 2 | md5sum
Abbiamo imitato il comportamento di BSD find -s
aggiungendo una chiamata a sort
. Il -k 2
bit gli dice di saltare l'hash MD5, quindi ordina solo i nomi dei file, che sono nel campo 2 fino alla fine della riga per sort
sta facendo i conti.
C'è un punto debole in questa versione del comando, che è che può confondersi se hai nomi di file con nuove righe, perché sembreranno più righe per sort
chiamata. Il find -s
variant non ha questo problema, perché l'attraversamento e l'ordinamento dell'albero avvengono all'interno dello stesso programma, find
.
In entrambi i casi, l'ordinamento è necessario per evitare falsi positivi:i più comuni filesystem Unix/Linux non mantengono gli elenchi delle directory in un ordine stabile e prevedibile. Potresti non rendertene conto usando ls
e simili, che ordinano silenziosamente il contenuto della directory per te. Chiamando find
senza ordinare il suo output in qualche modo farà sì che l'ordine delle righe nell'output corrisponda all'ordine che il filesystem sottostante le restituisce, il che farà sì che questo comando dia un valore hash modificato se l'ordine dei file assegnatogli come input cambia, anche se i dati rimangono identici.
Potresti chiedere se il -k 2
bit in GNU sort
il comando sopra è necessario. Dato che l'hash dei dati del file è un proxy adeguato per il nome del file purché il contenuto non sia cambiato, non otterremo falsi positivi se eliminiamo questa opzione, consentendoci di utilizzare lo stesso comando sia con GNU che BSD sort
. Tuttavia, renditi conto che c'è una piccola possibilità (1:2 con MD5) che l'ordine esatto dei nomi dei file non corrisponda all'ordine parziale che fa senza -k 2
può dare se c'è mai una collisione di hash. Tieni presente, tuttavia, che se tali piccole possibilità di mancata corrispondenza sono importanti per la tua applicazione, l'intero approccio è probabilmente fuori questione per te.
Potrebbe essere necessario modificare il md5sum
comandi a md5
o qualche altra funzione hash. Se scegli un'altra funzione hash e hai bisogno della seconda forma del comando per il tuo sistema, potresti dover modificare il sort
comandare di conseguenza. Un'altra trappola è che alcuni programmi di somma dei dati non scrivono affatto un nome di file, un ottimo esempio è il vecchio sum
di Unix programma.
Questo metodo è alquanto inefficiente, chiamando md5sum
N+1 volte, dove N è il numero di file nell'albero, ma è un costo necessario per evitare l'hashing dei metadati di file e directory.
Opzione 2:confronta i dati e Metadati
Se devi essere in grado di rilevare qualsiasi cosa in un albero è cambiato, non solo il contenuto del file, chiedi a tar
per imballare il contenuto della directory per te, quindi inviarlo a md5sum
:
$ tar -cf - somedir | md5sum
Perché tar
vede anche i permessi dei file, la proprietà, ecc., questo rileverà anche le modifiche a queste cose, non solo le modifiche ai contenuti dei file.
Questo metodo è considerevolmente più veloce, poiché effettua un solo passaggio sull'albero ed esegue il programma hash solo una volta.
Come con il find
metodo basato sopra, tar
elaborerà i nomi dei file nell'ordine in cui il filesystem sottostante li restituisce. Potrebbe anche essere che nella tua applicazione, puoi essere sicuro che non accadrà. Posso pensare ad almeno tre diversi modelli di utilizzo in cui è probabile che sia il caso. (Non li elencherò, perché stiamo entrando in un territorio di comportamento non specificato. Ogni filesystem può essere diverso qui, anche da una versione del sistema operativo a quella successiva.)
Se ti ritrovi a ricevere falsi positivi, ti consiglio di utilizzare il find | cpio
opzione nella risposta di Gilles.