Come posso ottenere la somma MD5 del contenuto di una directory come una somma?


171

Il programma md5sum non fornisce checksum per le directory. Voglio ottenere un unico 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 fare questo?

Risposte:


187

Il modo giusto dipende esattamente dal motivo per cui stai chiedendo:

Opzione 1: confronta solo i dati

Se hai solo bisogno di un hash del contenuto del file dell'albero, questo funzionerà:

$ find -s somedir -type f -exec md5sum {} \; | md5sum

Questo prima riassume tutti i contenuti dei file singolarmente, in un ordine prevedibile, quindi passa quell'elenco di nomi di file e hash MD5 da eseguire l'hash stesso, dando un singolo valore che cambia solo quando cambia il contenuto di uno dei file nella struttura.

Sfortunatamente, find -sfunziona 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 sostituito find -scon una chiamata a sort. Il -k 2bit gli dice di saltare l'hash MD5, quindi ordina solo i nomi dei file, che sono nel campo 2 fino alla fine della riga, secondo sorti calcoli.

C'è una debolezza con questa versione del comando, che è che potrebbe confondersi se ci sono nomi di file con nuove righe, perché sembreranno più righe alla sortchiamata. La find -svariante non ha questo problema, perché l'attraversamento e l'ordinamento degli alberi avvengono all'interno dello stesso programma find,.

In entrambi i casi, l'ordinamento è necessario per evitare falsi positivi: i filesystem Unix / Linux più comuni non mantengono gli elenchi di directory in un ordine stabile e prevedibile. Potresti non rendertene conto dall'uso lse simili, che ordinano silenziosamente il contenuto della directory per te. findsenza -so una sortchiamata stamperà i file nell'ordine in cui li restituiscono i filesystem sottostanti, il che farà sì che questo comando dia un valore hash modificato se l'ordine dei file che gli vengono dati come input cambia.

Potrebbe essere necessario modificare i md5sumcomandi md5o un'altra funzione hash. Se si sceglie un'altra funzione hash e si necessita della seconda forma del comando per il proprio sistema, potrebbe essere necessario modificare il sortcomando di conseguenza. Un'altra trappola è che alcuni programmi di somma dei dati non scrivono affatto un nome di file, ad esempio il vecchio sumprogramma Unix .

Questo metodo è in qualche modo inefficiente, chiamando md5sumN + 1 volte, dove N è il numero di file nella struttura, ma è un costo necessario per evitare hash e metadati della directory.

Opzione 2: confronta dati e metadati

Se devi essere in grado di rilevare che qualcosa è cambiato in un albero, non solo il contenuto del file, chiedi tardi impacchettare il contenuto della directory per te, quindi invialo a md5sum:

$ tar -cf - somedir | md5sum

Poiché tarvede anche le autorizzazioni dei file, la proprietà, ecc., Questo rileverà anche le modifiche a tali elementi, non solo le modifiche al contenuto del file.

Questo metodo è considerevolmente più veloce, poiché effettua solo un passaggio sull'albero ed esegue il programma hash solo una volta.

Come per il findmetodo basato sopra, tarelabora i nomi dei file nell'ordine in cui li restituisce il file system sottostante. Potrebbe essere che nella tua applicazione, puoi essere sicuro di non far sì che ciò accada. Posso pensare ad almeno tre diversi schemi di utilizzo in cui è probabile che ciò avvenga. (Non li elencherò, perché stiamo entrando in un territorio di comportamento non specificato. Ogni file system può essere diverso qui, anche da una versione del sistema operativo alla successiva.)

Se ti accorgi che stai ottenendo falsi positivi, ti consiglio di find | cpioscegliere l' opzione nella risposta di Gilles .


7
Penso che sia meglio navigare nella directory che viene confrontata e usare al find .posto di find somedir. In questo modo i nomi dei file sono gli stessi quando si forniscono specifiche di percorso diverse da trovare; questo può essere difficile :-)
Abbafei,

Dovremmo anche ordinare i file?
CMCDragonkai,

@CMCDragonkai: cosa intendi? Nel primo caso, ci facciamo ordinare l'elenco dei nomi dei file. Nel secondo caso, abbiamo volutamente non lo facciamo perché parte del sottolineato nulla nella prima frase è che l'ordine di file in una directory è cambiato, quindi non si vuole ordinare nulla.
Warren Young,

@WarrenYoung Puoi spiegarci un po 'più a fondo perché l'opzione 2 non è sempre migliore? Sembra essere più veloce, più semplice e più multipiattaforma. In tal caso non dovrebbe essere l'opzione 1?
Robin Winslow,

Opzione 1 alternativa: find somedir -type f -exec sh -c "openssl dgst -sha1 -binary {} | xxd -p" \; | sort | openssl dgst -sha1ignorare tutti i nomi di file (dovrebbe funzionare con le nuove righe)
windm,

38

Il checksum deve avere una rappresentazione deterministica e inequivocabile dei file come stringa. Deterministico significa che se metti gli stessi file nelle stesse posizioni, otterrai lo stesso risultato. Univoco significa che due diversi set di file hanno rappresentazioni diverse.

Dati e metadati

Fare un archivio contenente i file è un buon inizio. Questa è una rappresentazione inequivocabile (ovviamente, poiché puoi recuperare i file estraendo l'archivio). Può includere metadati di file come date e proprietà. Tuttavia, questo non è ancora del tutto corretto: un archivio è ambiguo, perché la sua rappresentazione dipende dall'ordine in cui sono archiviati i file e, se applicabile, dalla compressione.

Una soluzione è ordinare i nomi dei file prima di archiviarli. Se i nomi dei tuoi file non contengono newline, puoi eseguirli find | sortper elencarli e aggiungerli all'archivio in questo ordine. Fai attenzione a dire all'archiviatore di non ricorrere alle directory. Ecco alcuni esempi con POSIX pax, GNU tar e cpio:

find | LC_ALL=C sort | pax -w -d | md5sum
find | LC_ALL=C sort | tar -cf - -T - --no-recursion | md5sum
find | LC_ALL=C sort | cpio -o | md5sum

Solo nomi e contenuti, il modo a bassa tecnologia

Se si desidera solo tenere conto dei dati del file e non dei metadati, è possibile creare un archivio che includa solo il contenuto del file, ma non esistono strumenti standard. Invece di includere il contenuto del file, è possibile includere l'hash dei file. Se i nomi dei file non contengono newline e ci sono solo file e directory regolari (nessun link simbolico o file speciale), questo è abbastanza facile, ma devi occuparti di alcune cose:

{ export LC_ALL=C;
  find -type f -exec wc -c {} \; | sort; echo;
  find -type f -exec md5sum {} + | sort; echo;
  find . -type d | sort; find . -type d | sort | md5sum;
} | md5sum

Includiamo un elenco di directory oltre all'elenco dei checksum, poiché altrimenti le directory vuote sarebbero invisibili. L'elenco dei file è ordinato (in una locale specifica e riproducibile - grazie a Peter.O per avermelo ricordato). echosepara le due parti (senza questo, è possibile creare alcune directory vuote il cui nome sembra md5sumoutput che potrebbe passare anche per i file ordinari). Includiamo anche un elenco di dimensioni di file, per evitare attacchi con estensione di lunghezza .

A proposito, MD5 è deprecato. Se è disponibile, considera l'utilizzo di SHA-2 o almeno SHA-1.

Nomi e dati, che supportano le nuove linee nei nomi

Ecco una variante del codice sopra che si basa su strumenti GNU per separare i nomi dei file con byte null. Ciò consente ai nomi dei file di contenere nuove righe. Le utility di digest GNU citano caratteri speciali nel loro output, quindi non ci saranno nuove linee ambigue.

{ export LC_ALL=C;
  du -0ab | sort -z; # file lengths, including directories (with length 0)
  echo | tr '\n' '\000'; # separator
  find -type f -exec sha256sum {} + | sort -z; # file hashes
  echo | tr '\n' '\000'; # separator
  echo "End of hashed data."; # End of input marker
} | sha256sum

Un approccio più solido

Ecco uno script Python minimamente testato che crea un hash che descrive una gerarchia di file. Prende directory e contenuti dei file negli account e ignora i collegamenti simbolici e altri file e restituisce un errore irreversibile se non è possibile leggere alcun file.

#! /usr/bin/env python
import hashlib, hmac, os, stat, sys
## Return the hash of the contents of the specified file, as a hex string
def file_hash(name):
    f = open(name)
    h = hashlib.sha256()
    while True:
        buf = f.read(16384)
        if len(buf) == 0: break
        h.update(buf)
    f.close()
    return h.hexdigest()
## Traverse the specified path and update the hash with a description of its
## name and contents
def traverse(h, path):
    rs = os.lstat(path)
    quoted_name = repr(path)
    if stat.S_ISDIR(rs.st_mode):
        h.update('dir ' + quoted_name + '\n')
        for entry in sorted(os.listdir(path)):
            traverse(h, os.path.join(path, entry))
    elif stat.S_ISREG(rs.st_mode):
        h.update('reg ' + quoted_name + ' ')
        h.update(str(rs.st_size) + ' ')
        h.update(file_hash(path) + '\n')
    else: pass # silently symlinks and other special files
h = hashlib.sha256()
for root in sys.argv[1:]: traverse(h, root)
h.update('end\n')
print h.hexdigest()

OK, funziona, grazie. Ma c'è un modo per farlo senza includere metadati? In questo momento ne ho bisogno solo per i contenuti reali.

Che ne dici LC_ALL=C sortdi controllare da diversi ambienti ... (+ 1 a proposito)
Peter.O

Hai creato un intero programma Python per questo? Grazie! Questo è davvero più di quanto mi aspettassi. :-) Ad ogni modo, controllerò questi metodi e la nuova opzione 1 di Warren.

Buona risposta. L'impostazione dell'ordinamento con LC_ALL=Cè essenziale se in esecuzione su più macchine e sistemi operativi.
Assapora Cubranic il

Cosa cpio -o -significa? Cpio non usa stdin / out di default? GNU cpio 2.12 producecpio: Too many arguments
Jan Tojnar il

12

Dai un'occhiata a md5deep . Alcune delle funzionalità di md5deep che potrebbero interessarti:

Operazione ricorsiva - md5deep è in grado di esaminare in modo ricorsivo un intero albero di directory. Cioè, calcola MD5 per ogni file in una directory e per ogni file in ogni sottodirectory.

Modalità confronto: md5deep può accettare un elenco di hash noti e confrontarli con un set di file di input. Il programma può visualizzare quei file di input che corrispondono all'elenco di hash noti o quelli che non corrispondono.

...


Bello, ma non riesco a farlo funzionare, dice .../foo: Is a directory, cosa dà?
Camilo Martin,

3
Di per sé md5deep non risolve il problema dell'OP in quanto non stampa un md5sum consolidato, ma stampa semplicemente il md5sum per ogni file nella directory. Detto questo, puoi md5sum l'output di md5deep - non esattamente quello che voleva l'OP, ma è vicino! ad es. per la directory corrente: md5deep -r -l -j0 . | md5sum(dove -rè ricorsivo, -lsignifica "usa percorsi relativi" in modo che il percorso assoluto dei file non interferisca quando si tenta di confrontare il contenuto di due directory e -j0significa utilizzare 1 thread per prevenire il non determinismo dovuto a singoli md5sums restituiti in diversi ordini).
Stevie,

Come ignorare alcuni file / directory nel percorso?
Sandeepan Nath,

9

Se il tuo obiettivo è solo quello di trovare differenze tra due directory, considera l'utilizzo di diff.

Prova questo:

diff -qr dir1 dir2

Sì, anche questo è utile. Penso che tu intendessi dir1 dir2 in quel comando.

1
Di solito non uso le GUI quando posso evitarle, ma per la differenza di directory kdiff3 è eccezionale e funziona anche su molte piattaforme.
sinelaw,

File diversi vengono segnalati anche con questo comando.
Serge Stroobandt,

7

È possibile eseguire l'hashing di ogni file in modo ricorsivo e quindi eseguire l'hashing del testo risultante:

> md5deep -r -l . | sort | md5sum
d43417958e47758c6405b5098f151074 *-

è richiesto md5deep .


1
invece di md5deepusarlo hashdeepsu Ubuntu 16.04 perché il pacchetto md5deep è solo un manichino di transizione per hashdeep.
palik,

1
Ho provato l'hashdeep. Produce non solo hash ma anche alcune intestazioni, incluso ## Invoked from: /home/myuser/dev/quale sia il tuo percorso attuale e ## $ hashdeep -s -r -l ~/folder/. Questo deve essere ordinato, quindi l'hash finale sarà diverso se cambi la cartella o la riga di comando correnti.
truf,

3

Solo contenuto del file , esclusi i nomi dei file

Avevo bisogno di una versione che controllava solo i nomi dei file perché i contenuti risiedono in directory diverse.

Questa versione (la risposta di Warren Young) mi ha aiutato molto, ma la mia versione di md5sumoutput mostra il nome del file (relativo al percorso da cui ho eseguito il comando), ei nomi delle cartelle erano diversi, quindi anche se i checksum dei singoli file corrispondevano, il checksum finale non 't.

Per risolvere questo, nel mio caso, avevo solo bisogno di eliminare il nome del file da ciascuna riga finddell'output (selezionare solo la prima parola come separata da spazi usando cut):

find -s somedir -type f -exec md5sum {} \; | cut -d" " -f1 | md5sum

Potrebbe essere necessario ordinare anche i checksum per ottenere un elenco riproducibile.
Devo dire che il

3

soluzione :

$ pip install checksumdir
$ checksumdir -a md5 assets/js
981ac0bc890de594a9f2f40e00f13872
$ checksumdir -a sha1 assets/js
88cd20f115e31a1e1ae381f7291d0c8cd3b92fad

funziona in modo rapido e semplice soluzione quindi bash scripting.

vedi doc: https://pypi.python.org/pypi/checksumdir/1.0.5


se non hai pip potresti aver bisogno di installarlo con yum -y install python-pip (o dnf / apt-get)
DmitrySemenov

3

nix-hashdal gestore pacchetti Nix

Il comando nix-hash calcola l'hash crittografica del contenuto di ciascun percorso e lo stampa sull'output standard. Per impostazione predefinita, calcola un hash MD5, ma sono disponibili anche altri algoritmi di hash. L'hash è stampato in esadecimale.

L'hash viene calcolato su una serializzazione di ogni percorso: un dump dell'albero del file system radicato nel percorso. Ciò consente di eseguire l'hash delle directory e dei collegamenti simbolici nonché dei file regolari. Il dump è nel formato NAR prodotto da nix-store --dump. Pertanto, il percorso hash nix produce lo stesso hash crittografico del percorso - dump di nix-store | md5sum.


2

Uso questo frammento per volumi moderati :

find . -xdev -type f -print0 | LC_COLLATE=C sort -z | xargs -0 cat | md5sum -

e questo per XXXL :

find . -xdev -type f -print0 | LC_COLLATE=C sort -z | xargs -0 tail -qc100 | md5sum -


Cosa fa la -xdevbandiera?
Czerasz,

Ti richiede di digitare: man finde leggere quel bel manuale;)
poige

Buon punto :-). -xdev Don't descend directories on other filesystems.
Czerasz,

1
Nota che questo ignora i nuovi file vuoti (come se tocchi un file).
Ron John

Ci sono molti casi in cui questo produrrà lo stesso md5sum con una struttura di file e directory completamente diversa. La ridenominazione di file e directory non cambierà affatto ciò se non cambia l'ordinamento dei file. Quindi non consiglierei questo approccio.
Hans-Peter Störr,

2

Un buon controllo degli alberi è l'id albero di Git.

Sfortunatamente non è disponibile uno strumento autonomo in grado di farlo (almeno non lo so), ma se hai Git a portata di mano puoi semplicemente fingere di impostare un nuovo repository e aggiungere i file che vuoi controllare all'indice.

Ciò consente di produrre l'hash dell'albero (riproducibile), che include solo contenuto, nomi di file e alcune modalità di file ridotte (eseguibili).


2

Come seguito a questa eccellente risposta , se ti accorgi di voler accelerare il calcolo del checksum per una directory di grandi dimensioni, prova GNU Parallel :

find -s somedir -type f | parallel -k -n 100 md5 {} | md5

(Questo utilizza un Mac con md5, sostituirlo secondo necessità.)

Il -kflag è importante, che indica paralleldi mantenere l'ordine, altrimenti la somma complessiva può cambiare per essere eseguita anche se i file sono tutti uguali. -n 100dice di eseguire ogni istanza md5con 100 argomenti, questo è un parametro che puoi modificare per il miglior tempo di esecuzione. Vedi anche -Xflag di parallel(anche se nel mio caso personale che ha causato un errore.)


1

Uno script che è ben testato e supporta una serie di operazioni tra cui la ricerca di duplicati, il confronto di dati e metadati, che mostra aggiunte, nonché modifiche e rimozioni, ti potrebbe piacere Fingerprint .

L'impronta digitale in questo momento non produce un unico checksum per una directory, ma un file di trascrizione che include checksum per tutti i file in quella directory.

fingerprint analyze

Questo genererà index.fingerprintnella directory corrente che include checksum, nomi di file e dimensioni dei file. Di default usa sia MD5e SHA1.256.

In futuro, spero di aggiungere il supporto per Merkle Trees in Fingerprint che ti darà un unico checksum di alto livello. Al momento, è necessario conservare quel file per eseguire la verifica.


1

Non volevo nuovi eseguibili né soluzioni ingombranti, quindi ecco la mia opinione:

#!/bin/sh
# md5dir.sh by Camilo Martin, 2014-10-01.
# Give this a parameter and it will calculate an md5 of the directory's contents.
# It only takes into account file contents and paths relative to the directory's root.
# This means that two dirs with different names and locations can hash equally.

if [[ ! -d "$1" ]]; then
    echo "Usage: md5dir.sh <dir_name>"
    exit
fi

d="$(tr '\\' / <<< "$1" | tr -s / | sed 's-/$--')"
c=$((${#d} + 35))
find "$d" -type f -exec md5sum {} \; | cut -c 1-33,$c- | sort | md5sum | cut -c 1-32

0

Un approccio solido e pulito

  • Per prima cosa, non limitarti alla memoria disponibile ! Hash di un file in blocchi piuttosto che alimentare l'intero file.
  • Approcci diversi per esigenze / scopi diversi (tutto quanto segue o scegli ciò che mai si applica):
    • Hash solo il nome della voce di tutte le voci nella struttura di directory
    • Hash il contenuto del file di tutte le voci (lasciando il meta come, il numero di inode, ctime, atime, mtime, dimensione, ecc., Ottieni l'idea)
    • Per un collegamento simbolico, il suo contenuto è il nome del referente. Hash o scegliere di saltare
    • Segui o non seguire (nome risolto) il collegamento simbolico mentre esegui l'hashing del contenuto della voce
    • Se è una directory, i suoi contenuti sono solo voci di directory. Durante l'attraversamento ricorsivo alla fine verranno sottoposti a hash, ma i nomi delle voci della directory di quel livello dovrebbero essere sottoposti a hash per taggare questa directory? Utile nei casi d'uso in cui è richiesto l'hash per identificare rapidamente un cambiamento senza dover attraversare profondamente per hash il contenuto. Un esempio potrebbe essere la modifica del nome di un file, ma il resto del contenuto rimane lo stesso e sono tutti file abbastanza grandi
    • Gestisci bene file di grandi dimensioni (di nuovo, attenzione alla RAM)
    • Gestire alberi di directory molto profondi (attenzione ai descrittori di file aperti)
    • Gestire nomi di file non standard
    • Come procedere con file che sono socket, pipe / FIFO, dispositivi a blocchi, dispositivi char? Devono averli anche loro?
    • Non aggiornare il tempo di accesso di nessuna voce durante l'attraversamento perché questo sarà un effetto collaterale e controproducente (intuitivo?) Per alcuni casi d'uso.

Questo è quello che ho in testa, chiunque abbia trascorso un po 'di tempo a lavorare su questo praticamente avrebbe catturato altri gotcha e casi d'angolo.

Ecco uno strumento (dichiarazione di non responsabilità: sono un collaboratore ad esso) dtreetrawl , molto leggero sulla memoria, che affronta la maggior parte dei casi, potrebbe essere un po 'ruvido attorno ai bordi ma è stato abbastanza utile.

Usage:
  dtreetrawl [OPTION...] "/trawl/me" [path2,...]

Help Options:
  -h, --help                Show help options

Application Options:
  -t, --terse               Produce a terse output; parsable.
  -d, --delim=:             Character or string delimiter/separator for terse output(default ':')
  -l, --max-level=N         Do not traverse tree beyond N level(s)
  --hash                    Hash the files to produce checksums(default is MD5).
  -c, --checksum=md5        Valid hashing algorithms: md5, sha1, sha256, sha512.
  -s, --hash-symlink        Include symbolic links' referent name while calculating the root checksum
  -R, --only-root-hash      Output only the root hash. Blank line if --hash is not set
  -N, --no-name-hash        Exclude path name while calculating the root checksum
  -F, --no-content-hash     Do not hash the contents of the file

Un esempio di output amico dell'uomo:

...
... //clipped
...
/home/lab/linux-4.14-rc8/CREDITS
        Base name                    : CREDITS
        Level                        : 1
        Type                         : regular file
        Referent name                :
        File size                    : 98443 bytes
        I-node number                : 290850
        No. directory entries        : 0
        Permission (octal)           : 0644
        Link count                   : 1
        Ownership                    : UID=0, GID=0
        Preferred I/O block size     : 4096 bytes
        Blocks allocated             : 200
        Last status change           : Tue, 21 Nov 17 21:28:18 +0530
        Last file access             : Thu, 28 Dec 17 00:53:27 +0530
        Last file modification       : Tue, 21 Nov 17 21:28:18 +0530
        Hash                         : 9f0312d130016d103aa5fc9d16a2437e

Stats for /home/lab/linux-4.14-rc8:
        Elapsed time     : 1.305767 s
        Start time       : Sun, 07 Jan 18 03:42:39 +0530
        Root hash        : 434e93111ad6f9335bb4954bc8f4eca4
        Hash type        : md5
        Depth            : 8
        Total,
                size           : 66850916 bytes
                entries        : 12484
                directories    : 763
                regular files  : 11715
                symlinks       : 6
                block devices  : 0
                char devices   : 0
                sockets        : 0
                FIFOs/pipes    : 0

I consigli generali sono sempre ben accetti, ma le risposte migliori sono specifiche e con il codice ove appropriato. Se hai esperienza nell'uso dello strumento a cui ti riferisci, includilo.
Bu5hman

@ bu5hman Certo! Non mi sentivo abbastanza a mio agio nel dire (gongolando?) Di più su quanto funzioni bene da quando sono coinvolto nel suo sviluppo.
sei-k,

0

Fare individualmente per tutti i file in ogni directory.

# Calculating
find dir1 | xargs md5sum > dir1.md5
find dir2 | xargs md5sum > dir2.md5
# Comparing (and showing the difference)
paste <(sort -k2 dir1.md5) <(sort -k2 dir2.md5) | awk '$1 != $3'

0

La migrazione al formato di archivio POSIX influenza i checksum basati su Tar GNU

Questa risposta vuole essere un aggiornamento supplementare all'approccio dell'utilizzo dell'output Tar per eseguire l'hashing del contenuto delle directory, come è stato proposto (tra le altre cose) nelle eccellenti risposte di Warren Young e Gilles qualche tempo fa.

Da allora, almeno openSUSE (dalla sua versione 12.2) ha cambiato il suo formato GNU Tar predefinito da "GNU tar 1.13.x format" al (leggermente) superiore "POSIX 1003.1-2001 (pax) format" . Anche a monte (tra gli sviluppatori di GNU Tar) discutono per eseguire la stessa migrazione, vedi ad esempio l'ultimo paragrafo in questa pagina del manuale di GNU Tar :

Il formato predefinito per tar GNU è definito al momento della compilazione. Puoi verificarlo eseguendo tar --helped esaminando le ultime righe del suo output. Di solito, tar GNU è configurato per creare archivi in gnuformato, tuttavia, la versione futura passerà a posix.

(Questa pagina offre anche una bella recensione sui diversi formati di archivio disponibili con GNU Tar.)

Nel nostro caso, dove tariamo il contenuto della directory e cancelliamo il risultato, e senza prendere misure specifiche, un passaggio dal formato GNU a POSIX ha le seguenti conseguenze:

  • Nonostante il contenuto di directory identico, il checksum risultante sarà diverso.

  • Nonostante il contenuto identico della directory, il checksum risultante sarà diverso da run to run se vengono utilizzate le intestazioni pax predefinite.

Quest'ultimo deriva dal fatto che il formato POSIX (pax) include intestazioni di pax estese che sono determinate da una stringa di formato predefinita %d/PaxHeaders.%p/%fin GNU Tar. All'interno di questa stringa, l' %pidentificatore viene sostituito dall'ID di processo del processo Tar di generazione, che ovviamente è diverso da corsa a corsa. Vedi questa sezione del manuale GNU Tar e in particolare questa per i dettagli.

Proprio ora, risalente al 28-03-2019, è stato accettato un commit a monte che disinnesta questo problema.

Quindi, per poter continuare a usare GNU Tar nel caso d'uso dato, posso raccomandare le seguenti opzioni alternative:

  • Usa l'opzione Tar --format=gnuper dire esplicitamente a Tar di generare l'archivio nel formato "vecchio". Questo è obbligatorio per validare "vecchi" checksum.

  • Utilizzare il formato POSIX più recente, ma specificare esplicitamente un'intestazione pax adatta, ad esempio da --pax-option="exthdr.name=%d/PaxHeaders/%f". Tuttavia, ciò interrompe la retrocompatibilità con i "vecchi" checksum.

Ecco un frammento di codice Bash che uso regolarmente per calcolare i checksum dei contenuti della directory inclusi i metadati:

( export LC_ALL=C
  find <paths> ! -type s -print0 |
  sort -z |
  tar cp --format=gnu --numeric-owner \
         --atime-preserve \
         --no-recursion --null --files-from - |
  md5sum --binary; )

Qui, <paths>viene sostituito da un elenco separato da spazi dei percorsi di tutte le directory che voglio essere coperto dal checksum. Lo scopo dell'uso della locale C, della separazione dei byte di nomi di byte null e dell'utilizzo di find and sort per ottenere un ordine indipendente dei file system dei file nell'archivio è già sufficientemente discusso in altre risposte.

Le parentesi circostanti mantengono l' LC_ALLimpostazione locale in una subshell.

Inoltre, uso l'espressione ! -type scon findper evitare avvisi da Tar che si verificano se i file socket fanno parte del contenuto della directory: GNU Tar non archivia i socket. Se si preferisce ricevere una notifica relativa ai socket ignorati, lasciare quell'espressione.

Uso --numeric-ownercon Tar, per poter verificare in seguito i checksum anche sui sistemi, dove non sono noti tutti i proprietari di file.

L' --atime-preserveopzione per Tar è meglio omessa se una qualsiasi delle <paths>bugie su un dispositivo montato di sola lettura. Altrimenti verrai avvisato per ogni singolo file il cui timestamp di accesso Tar non è stato in grado di ripristinare. Per la scrittura abilitata <paths>, uso questa opzione, bene, per preservare i timestamp di accesso nelle directory con hash.

L'opzione Tar --no-recursion, che era già stata utilizzata nella proposta di Gilles , impedisce a Tar di ricadere ricorsivamente nelle directory da solo, e di operare invece file per file su qualsiasi cosa venga alimentata finddall'output ordinato .

E infine, non è vero che io uso md5sum: effettivamente uso sha256sum.


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.