sam mam zkusenost, ze delat hash jednotlivych souboru a porovnavat je overkill.
Nie celkom, už som to robil niekoľkokrát v rôznych verziách so stovkami tisíc súborov. Zvlášť keď sa jedná iba o deduplikáciu, ktorá je oveľa menej náročná ako sa zdá. Vidím tam Windows, používam na takéto veci PowerShell je na to ako stvorený, má prístup aj do .Net aj do Windows API, dajú sa v ňom písať aj testy aj tam funguje TDD. A to isté by malo fungovať aj na Linuxe, v rámci .Net Core, tuším. Prípadne python alebo C# alebo čokoľvek.
Postup v skratke pre PowerShell: získať položky súborov v daných zložkách, to sú objekty, asi typ FileInfo alebo niečo také, zoskupiť podľa veľkosti, iba súbory s rovnakou veľkosťou (celkovo alebo veľkosť prúdu audio/video dát, ak ignorujem popisky) môžu byť duplikáty; pre každú skupinu veľkosti (cyklus alebo ForEach-Objekt) ktorá má viac ako jedného člena pridať objektom FileInfo v aktuálnej skupine cez Add-Member ako vlastnosť prúd na čítanie bloku dát, pridať aj objekt .Net na inkrementálný hash, zistiť si vopred z úložiska minimálnu veľkosť bloku, ktorú má zmysel načítať z disku (lebo keď aj zadám iba 1 bajt, OS aj tak načíta napríklad 4kb), pre danú veľkosť vypočítať koľko blokov zistenej veľkosti potrebujem na danú veľkosť súboru. Počet blokov určí počet iterácii inkrementálneho hashovania, pre každú iteráciu poslať položky aktuálnej skupiny veľkosti súborov do ForEach-Objekt, pre každú položku v bloku toho ForEach-Objekt načítať pre danú iteráciu i-ty blok podľa čísla iterácie, z prúdu, ktorý bol pridaný do položky v predchádzajúcich krokoch, pridať načítané dáta do kontrolného súčtu cez objekt z .Net, ktorý bol tiež pridaný do položky a vrátiť položku ako výsledok. Plus mínus niečo na tento spôsob.
Pokiaľ takto spracované položky chcem zhromaždené v jednom poli, tak ich normálne priradím do premennej, ak nie, tak ich zreťazím v kolóne s ďalším krokom, tým ten ForEach-Objekt nie je blokujúci, ale je ako generátorová korutina, ktorá posiela položky ďalej do ďalšieho kroku, takže keď napríklad v prvom kroku kolóny je piata položka, prvá položka je už v piatom kroku kolóny, ak ani jeden z krokov nie je blokujúci. (+-1, nerozmýšľam, nepočítam to...)
Ďalším krokom tu ale je zoskupenie podľa aktuálnej hodnoty inkrementálneho kontrolného súčtu. To sa asi dá urobiť iba blokujúco, lebo sú nutné všetky položky.
Tým vzniknú skupiny podľa aktuálnej hodnoty inkrementálneho kontrolného súčtu, tie ktoré po prvej iterácii majú iba jedného člena nemajú rovnaký prvý blok, nie sú to teda duplikáty, tým treba iba zatvoriť prúd, prípadne odobrať a aj ten objekt .Net, ktorý inkrementálne hashuje a zabudnúť na ne.
Súbory v skupinách, ktoré majú viac ako jedného člena sú kandidáti na duplikáty a tie je treba v ďalšej iterácii poslať opäť do toho ForEach-Objekt, kde sa načíta druhý blok dát, pridá sa do inkrementálneho kontrolného súčtu a výsledok sa zas zoskupí podľa aktuálnej hodnoty kontrolného súčtu z prvých dvoch blokov.
Takto postupne vypadnú súbory, ktoré nie sú duplikáty, veľa z nich hneď v prvých iteráciách, pre veľa z nich sa teda kontrolný súčet počíta iba z blokov na začiatku, dovtedy, kým nevypadnú z hry a úplný kontrolný súčet sa vypočíta iba z tých súborov, ktoré naozaj duplikátmi sú.
Takže pre deduplikáciu nie je nutné počítať celé kontrolné súčty zo všetkých súborov.
ForEach-Objekt má aj paralelnú verziu, ale je to zložitejšie, lebo je nutné obmedziť podľa typu úložiska počet paralelne bežiacich úloh (NVME zvládne viac, SATA SSD menej, rotačný disk ešte menej, možno iba 1, sieťové som neskúšal), pokiaľ máte všetko z NVME, je to jednoduché, ak nie, tak sa to dá zoskupiť podľa druhu úložiska a jednotlivé skupiny podľa druhu hardvéru riešite oddelene s rôznym obmedzením súbežnosti a pred zoskupením podľa výsledku aktuálnej iterácie kontrolného súčtu to zlúčite do jedného poľa. V PowerShelli je to iba jedna ďalšia úroveň cyklu a to zlúčenie je vzhľadom na vlastnosti kolóny automatické.
Potom sú tam ešte také veci ako odkazy na súbory, pevné alebo symbolické, to je nutné vedieť rozlíšiť, získať cieľový súbor odkazu, nechať v sade iba jeden výskyt, nemá zmysel deduplikovať 10 súborov, keď všetky ukazujú na tie isté dáta, to zistíte aj z Windows API, že sú to fyzicky tie isté dáta prístupné pod viacerými názvami a je lepšie prefiltrovať to vopred.
Robil som aj presúvanie súborov v jednej stromovej štruktúre podľa vzoru ich umiestnenia v inej stromovej štruktúre, a podobné veci, to ale vyžaduje buď úplné kontrolné súčty pre všetko, alebo podľa typu dát, napríklad audio/video súbory sa dá tipnúť si, že keď sú dáta v strede rôzne, celý súbor je rôzny, tak stačí kontrolný súčet z kúsku dát.