Pokud potřebujete na Debianu 10 ověřit změnu souboru (např. že během kopírování nebyl poškozen)…
Pro svůj systém zálohování potřebuji skript, který ke každému souboru vyrobí unikátní otisk (hash).
Takže třeba pro ahoj.txt
vyrobí ahoj.hash
obsahující otisk souboru ahoj.txt
.
Protože počítám se zálohováním hromady malých i dost velkých souborů, potřebuji opravdu rychlou funkci, která zvládne např. hash DVD v rozumném čase. Přesně takovou funkcí by měl být algoritmus xxhash.
sudo apt update sudo apt-get install xxhash
xxh64sum <soubor>
vypíše hash spočítaný 64bitovým algoritmem a název souboruxxh64sum ahoj.txt > ahoj.check
xxh64sum -c ahoj.check
- tady se provede kontrola, zda soubor v ahoj.check
existuje a je nezměněný. Výsledkem je název souboru a OK nebo FAILEDls -I *.hash | xargs xxh64sum > soubory.hash
-I *.hash
) protože by se mi ohashoval i samotný výsledek (a to nechci)xxh64sum -c soubory.hash | grep ': FAILED' | awk -F: '{print $1}' > zmenene.hash
zmenene.hash
vypíše seznam změněných souborů-F:
říká, že oddělovačem pro awk bude dvojtečka a print $1
zase že chceme vypsat první sloupecuser@srv:~$ ls test2.txt test3.txt test.txt user@srv:~$ ls -I *.hash | xargs xxh64sum > soubory.hash user@srv:~$ cat soubory.hash 4eaa915d9d571b1e test2.txt 1f57dd2f7c75f00b test3.txt 6659c6ffae797c28 test.txt user@srv:~$ echo a jeste neco >> test3.txt user@srv:~$ cat test3.txt nejaky dalsi text bla bla bla bla bla a jeste neco user@srv:~$ xxh64sum -c soubory.hash test2.txt: OK test3.txt: FAILED test.txt: OK 1 computed checksums did NOT match user@srv:~$ xxh64sum -c soubory.hash | grep ': FAILED' | awk -F: '{print $1}' > zmenene.hash user@srv:~$ cat zmenene.hash test3.txt
Zpátky k zadání - zde je skript, který vezme parametry a pro každý z nich vyrobí soubor s příponou .hash obsahující jeho hash:
#!/bin/bash args=("$@") args_cnt=${#args[@]} for ((i=0;i<$args_cnt;i++)); do soubor=${args[${i}]} vynechat=".*\.(hash|archived)$" # pokud je na vstupu .hash nebo .archived soubor, pak jej vynechame if [[ ! $soubor =~ $vynechat ]]; then xxh64sum $soubor > $soubor.hash fi done
ahoj.txt
již existuje soubor ahoj.txt.hash
, přepíše jejuser@srv:~$ ls mkhash.sh test2.txt test3.txt test.txt user@srv:~$ ls -I *.sh | xargs ./mkhash.sh user@srv:~$ ls mkhash.sh test2.txt.hash test2.txt test3.txt.hash test3.txt test.txt.hash test.txt user@srv:~$ xxh64sum -c test3.txt.hash test3.txt: OK user@srv:~$
find . -type f
vypíše rekurzivně všechny soubory ve struktuře-exec
zde nepoužívám, protože do hash souborů chci celou relativní cestu, nikoli jen název souboru (to se mi hodí při zálohování)find
je zde/usr/local/sbin
usr@srv:/zaloha# ls -R .: druhy.txt prvni.archived prvni.txt test_dir ./test_dir: dalsi ./test_dir/dalsi: treti.txt usr@srv:/zaloha# find . -type f | xargs /usr/local/sbin/mkhash.sh usr@srv:/zaloha# ls -R .: druhy.txt druhy.txt.hash prvni.archived prvni.txt prvni.txt.hash test_dir ./test_dir: dalsi ./test_dir/dalsi: treti.txt treti.txt.hash usr@srv:/zaloha# find . -path "./*.hash" | xargs xxh64sum -c ./prvni.txt: OK ./druhy.txt: OK ./test_dir/dalsi/treti.txt: OK