Program md5sum neposkytuje kontrolní součty pro adresáře. Chci získat jeden kontrolní součet MD5 pro celý obsah adresáře, včetně souborů v podadresářích. To znamená jeden kombinovaný kontrolní součet vytvořený ze všech souborů. Existuje způsob, jak to udělat?
Přijatá odpověď:
Správný způsob závisí přesně na tom, proč se ptáte:
Možnost 1:Porovnat pouze data
Pokud potřebujete pouze hash obsahu souboru stromu, vystačíte si s tímto:
$ find -s somedir -type f -exec md5sum {} ; | md5sum
To nejprve shrne veškerý obsah souboru jednotlivě, v předvídatelném pořadí, poté předá tento seznam názvů souborů a hashů MD5, které mají být hašovány, čímž se získá jediná hodnota, která se změní pouze tehdy, když se změní obsah jednoho ze souborů ve stromu.
Bohužel find -s
funguje pouze s BSD find(1), používaným v macOS, FreeBSD, NetBSD a OpenBSD. Chcete-li získat něco srovnatelného na systému s GNU nebo SUS find(1), potřebujete něco trochu ošklivějšího:
$ find somedir -type f -exec md5sum {} ; | sort -k 2 | md5sum
Napodobili jsme chování BSD find -s
přidáním volání sort
. -k 2
bit mu říká, že má přeskočit hash MD5, takže třídí pouze názvy souborů, které jsou v poli 2 až na konci řádku podle sort
's zúčtování.
Slabinou této verze příkazu je, že může být zmatená, pokud máte nějaké názvy souborů s novými řádky, protože to bude vypadat jako více řádků v sort
volání. find -s
varianta tento problém nemá, protože k procházení a třídění stromu dochází v rámci stejného programu, find
.
V obou případech je řazení nezbytné, aby se zabránilo falešným poplachům:nejběžnější souborové systémy Unix/Linux neudržují seznamy adresářů ve stabilním a předvídatelném pořadí. Při použití ls
si to možná neuvědomujete a takové, které tiše třídí obsah adresáře za vás. Volání find
bez seřazení výstupu nějakým způsobem způsobí, že pořadí řádků na výstupu bude odpovídat jakémukoli pořadí, které jim základní souborový systém vrátí, což způsobí, že tento příkaz udělí změněnou hodnotu hash, pokud se změní pořadí souborů, které mu byly dány jako vstup, a to i pokud data zůstanou stejná.
Můžete se také zeptat, zda -k 2
bit v GNU sort
výše uvedený příkaz je nutný. Vzhledem k tomu, že hash dat souboru je adekvátní proxy pro jméno souboru, pokud se obsah nezmění, nezískáme falešné poplachy, pokud tuto možnost vynecháme, což nám umožní používat stejný příkaz s GNU i BSD sort
. Uvědomte si však, že existuje malá šance (1:2 s MD5), že přesné pořadí názvů souborů neodpovídá částečnému pořadí, v jakém je bez -k 2
může dát, pokud někdy dojde ke kolizi hash. Mějte však na paměti, že pokud u vaší aplikace záleží na tak malých pravděpodobností nesouladu, celý tento přístup pro vás pravděpodobně nepřichází v úvahu.
Možná budete muset změnit md5sum
příkazy do md5
nebo nějakou jinou hashovací funkci. Pokud zvolíte jinou hashovací funkci a potřebujete pro svůj systém druhou formu příkazu, možná budete muset upravit sort
podle toho příkaz. Další pastí je, že některé programy pro sčítání dat vůbec nezapisují název souboru, ukázkovým příkladem je starý unixový sum
program.
Tato metoda je poněkud neefektivní, volá md5sum
N+1 krát, kde N je počet souborů ve stromu, ale to je nezbytná cena, aby se zabránilo hašování metadat souborů a adresářů.
Možnost 2:Porovnání dat a Metadata
Pokud potřebujete být schopni to zjistit cokoli ve stromu se změnil, nejen obsah souboru, zeptejte se tar
zabalit obsah adresáře a odeslat jej na md5sum
:
$ tar -cf - somedir | md5sum
Protože tar
také vidí oprávnění k souboru, vlastnictví atd., toto také zjistí změny těchto věcí, nejen změny obsahu souboru.
Tato metoda je podstatně rychlejší, protože provede pouze jeden průchod stromem a spustí hashovací program pouze jednou.
Stejně jako u find
výše založená metoda, tar
zpracuje názvy souborů v pořadí, v jakém je základní souborový systém vrátí. Může se stát, že ve své aplikaci si můžete být jisti, že to nezpůsobíte. Napadají mě alespoň tři různé způsoby použití, kde tomu tak pravděpodobně bude. (Nebudu je vypisovat, protože se dostáváme do oblasti nespecifikovaného chování. Každý souborový systém se zde může lišit, dokonce i od jedné verze operačního systému k další.)
Pokud zjistíte, že dostáváte falešné poplachy, doporučuji použít find | cpio
možnost v Gillesově odpovědi.