Korupcija in kako jo ugotoviti
Pred nekaj leti mi je kolega fotograf omenil, da vestno skrbi za zdravstveno stanje svojih slik in da redno preverja ali so varnostne kopije še vedno enake kot originali. Seveda je tu mislil na datoteke, tako originale (raw) kot obdelane (TIFF in JPEG). Seveda je, kot pravi profesionalec, v ta namen kupil ustrezen software, ki pa ni bil ravno poceni.
Sprva ga nisem dobro razumel, a vame je zasadil črva, ki je vrtal in mi vnašal dvom o kvaliteti mojih varnostnih kopij. Ker sam nisem kaj preveč kopiral svojih datotek iz diska na disk, si s preverjanjem nisem preveč belil glave, sploh pa nisem videl smisla v plačevanju za software, ki bi ga uporabil le kdaj pa kdaj.
Zadnjič pa sem kupil nov Mac mini in seveda selil celotno zakladnico iz prenosnika nanj. Ob tem sem se ponovno spomnil na besede kolega in malce povrtal v zadevo.
Izkaže se, da vrli software zgolj izračuna MD5 hash (zgoščenko?) in ga shrani v datoteko z enakim imenom kot originalna slika, le končnico ima drugo. Drugi del programa pa na enak način ponovno izračunan MD5 hash primerja s tistim, ki je shranjen v datoteki. Če se hash-a ujemata je z datoteko vse v redu, drugače se je njena vsebina spremenila (verjetno je prišlo do okvare) in program na to opozori.
Ker ima OS X podlago v *NIX sistemu in ima v naboru ukazov tudi md5 s katerim lahko v Terminal-u izračunamo hash (datoteke) sem se lotil programiranja nadomestka za omenjeni software.
In moja programerska žilica mi ni dala miru, dokler nisem skupaj spravil dveh enovrstičnic, ki opravita vse zgoraj opisano. Seveda samo md5 ni dovolj, zato sem uporabil še nekaj ukazov, ki bi morali biti na voljo v skoraj vseh Linux in ostalih *NIX distribucijah.
Pa začnimo:
find -E . -iregex ".*\.(jpe?g|png|tiff?|cr[w2]|nef)" -type f -exec sh -c "[ ! -f '{}'.md5 ] && md5 -r '{}' | cut -c 1-32 > '{}'.md5" \;
... in poglejmo kaj kakšen del ukaza naredi.
- find - išče datoteke na disku, parametri pa pomenijo naslednje:
- -E : extended regex (OS X razširitev)
- . : išči v trenutni mapi in podmapah
- -iregex : case insensitive regular expression
- ".*\.(jpe?g|png|tiff?|cr[w2]|nef)" : regex, ki poišče vse slike (s končnicami: .jpg, .jpeg, .png, .tif, .tiff, .crw, .cr2 ter .nef)
- -type f : find naj išče samo datoteke
- -exec : za vsako najdeno datoteko izvedi ukaz
- sh -c "..." : zažene shell, ki mu posreduje ukaz v navednicah
- ukaz v navednicah je srce izračuna hasha in kreiranja datoteke
- [ ! -f '{}'.md5 ] : preveri ali (ne) obstaja datoteka s končnico .md5 in imenom kot originalna datoteka
- && : če datoteka ne obstaja izvedi naslednji ukaz
- md5 -r '{}' : izračuna MD5 hash in ga izpiše v stdout
- | : preusmeri stdout ukaza md5 v stdin za naslednji ukaz
- cut -c 1-32 : izreže (izlušči) prvih 32 znakov, ki jih je prebral iz stdin
- > '{}'.md5 : kreira datoteko s končnico .md5 in imenom kot original, ki vsebuje MD5 hash
... ter nadaljujmo s kontrolo:
find -E . -iregex ".*\.(jpe?g|png|tiff?|cr[w2]|nef)" -type f -exec sh -c "md5 -r '{}' | cut -c 1-32 | diff -q '{}'.md5 - | cut -f 2 -d \" \"" \;
.. tu pa lahko izluščimo naslednje.
- find - išče z enakimi kriteriji kot v prvem primeru
- večina ukazov, ki jih izvede shell je enakih kot prej, razlika je samo:
- ni kontrole o obstoječi datoteki .md5
- diff -q '{}'.md5 - : primerja vsebino datoteke .md5 in izračunanega MD5 (stdin), -q pomeni samo izpis ali sta vsebini različni, v primeru enakosti ne izpiše ničesar
- cut -f 2 -d " " : izlušči 2. polje (ime datoteke)
Seveda sem zadevo pognal na svoji 100GB veliki knjižnici in prvi prehod (kreiranje .md5 datotek) je trajal slabe pol ure. V tem času so poleg originalnih datotek slik nastale datoteke s končnico .md5.
Drugi prehod (kontrola) potrebuje ravno toliko časa saj ponovno preračunava hash, zato je bolje, da imamo več podmap in kontroliramo samo eno podmapo naenkrat.
Kdaj ukaza uporabiti?
Prvi ukaz, ki kreira .md5 datoteke, je najbolje da uporabimo, ko so slike (oz. druge datoteke) še na originalnem mediju (npr. CF ali SD kartici).
Ko nato (originalne) datoteke/slike kopiramo iz medija na medij ali v druge mape, kopiramo poleg tudi .md5 datoteke. Po končanem kopiranju poženemo drugi ukaz, ki preveri ali se je med kopiranjem vsebina datotek spremenila.
Že samo en spremenjen bit močno vpliva na izračunan MD5 hash zato je verjetnost, da odkrijemo napako, zeeeelooooo velika. In to je dobro!