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.checkxxh64sum -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.hashzmenene.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/sbinusr@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