Smazání souborů se stejným obsahem, ale jiným jménem

Zdravim

Nemuzu prijit na jednu vec. Mam ve slozce radove nekolik tisic souboru (vsechny soubory v jednom adresari, zadne podadresare) a nektere soubory jsou vice-nasobne tim zpusobem, ze se vyskytuje soubor s uplne stejnym obsahem nekolikrat v teto slozce, jenze pod jinymi jmeny a i datum posledni zmeny muze byt jiny (napr. totozny z datumem stazeni). Kdyz je soubor se stejnym obsahem jen pod jinym jmenem, tak by mel byt stejny kontrolni soucet, pokud je ale krome jmena jiny i datum, uz si tim nejsem jisty.

Mel by nekdo napad, jak v terminalu promazat vice-nasobne soubory (stejny obsah, ruzna jmena) a ponechat jen jeden soubor (soubor se jmenem, ktere je podle abecedniho razeni vice-nasobnych souboru na prvnim miste) ?
« Poslední změna: 09. 08. 2021, 19:08:53 od Petr Krčmář »


Re:Jak najit soubory se stejnym jmenem ale jinym obsahem a promazat
« Odpověď #1 kdy: 09. 08. 2021, 19:09:10 »
Kontrolní součet se počítá z obsahu souboru, tj. datum modifikace na něj nemá vliv.

Použijte sha1sum, sha256sum, b2sum nebo b3sum, tím vypočítáte kontrolní součty souborů.

Pak buď pomocí sort -u seřaďte dle hashe – parametr -u zajistí, že se duplicitní položky vypíšou pouze jednou. Výsledek bude seznam souborů, které se mají zachovat, zbytek jsou duplicity a ty můžete smazat.

Nebo výpis kontrolních součtů seřaďte pomocí sort a následně si pomocí uniq -d nechte vypsat jenom duplicitní hashe, pak si vyberte, který soubor k danému hashi chcete zachovat a ostatní smažte.

_Jenda

  • *****
  • 1 550
    • Zobrazit profil
    • https://jenda.hrach.eu/
    • E-mail
Re:Smazání souborů se stejným obsahem, ale jiným jménem
« Odpověď #2 kdy: 09. 08. 2021, 20:28:50 »
Program fdupes dělá přesně toto. Teda nezkoušel jsem to abecední řazení, ale podle manuálové stránky na to je volba -o.

Re:Smazání souborů se stejným obsahem, ale jiným jménem
« Odpověď #3 kdy: 10. 08. 2021, 15:37:58 »
Citace
for i in `sha256sum ./* | awk '{ print $1}'  | uniq -d -w64 `; do  rm -vf `sha256sum ./* | uniq -Dw64 | grep $i | tail +2 | awk '{print $2}'` ;done

 ;D ::)

Re:Smazání souborů se stejným obsahem, ale jiným jménem
« Odpověď #4 kdy: 10. 08. 2021, 18:26:17 »
Kód: [Vybrat]
for i in `sha256sum ./* | awk '{ print $1}'  | uniq -d -w64 `; do  rm -vf `sha256sum ./* | uniq -Dw64 | grep $i | tail +2 | awk '{print $2}'` ;done
;D ::)
Vždycky když vidím v nějakém příkazu u rm parametr -f jen tak kvůli tradici nebo pro jistotu, vzbudí to ve mně podezření o kvalitě toho kódu. Je to podobné, jako když někdo před všechno píše hlava nehlava sudo a vůbec neřeší, jestli náhodou už dávno není pod rootem. To -f je ale o generaci starší.

Pokud by ten adresář obsahoval hodně dat (ať už velké soubory, nebo hodně dat v menších souborech), počítat ty hashe dvakrát nemusí být úplně ideální.

Také nejsem úplně přesvědčen o tom, že tohle přežije bez úhony soubory \n v názvu nebo i s mezerou v názvu.

Každopádně na shellu jsou pozoruhodné dvě věci: kolik věcí se dá napsat jako one-liner a kolik je různých způsobů, jak smazat něco, co jste smazat nechtěl.


Re:Smazání souborů se stejným obsahem, ale jiným jménem
« Odpověď #5 kdy: 10. 08. 2021, 19:06:48 »
To som napisal narychlo, samozrejme ze ak ma v nazve \n tak to treba osetrit a suhlasim,ze tento pripad nie je vhodny ak su subory obrovske. A co je zle na rm -f netusim, ale pohoda.

Alebo skuste pane napisat vas kod, okrem teoretizovania ze ako by sa to dalo "nejako takhle" spravit ;)
« Poslední změna: 10. 08. 2021, 19:12:57 od snuff1987 »

Re:Smazání souborů se stejným obsahem, ale jiným jménem
« Odpověď #6 kdy: 10. 08. 2021, 19:35:14 »
A co je zle na rm -f netusim, ale pohoda.
Víte, co ten parametr -f dělá? rm pak ignoruje neexistující soubory a argumenty – což je přesně to, co v tomhle případě nechcete, protože se vám do seznamu zatoulal název souboru, který neexistuje, asi je se zpracováním názvů něco špatně, a je dost možné, že to také smaže něco, co jste smazat nechtěl. Dále -f zabraňuje potvrzovacím dotazům. Které se ale zobrazí, pokud chcete smazat soubor jen pro čtení (což je opět upozornění, že se děje něco divného), nebo pokud máte alias rm na rm -i. To -i ale lépe potlačíte pomocí -I, a hlavně je otázka, k čemu je dobré mít takovýhle alias a pak všude automaticky psát rm -f.

Alebo skuste pane napisat vas kod, okrem teoretizovania ze ako by sa to dalo "nejako takhle" spravit ;)
Myslím si, že je lepší naučit člověka chytat ryby, než mu jen jednu rybu ulovit. To, co jsem napsal, je podle mne dostatečné k tomu, aby si tazatel přečetl manuálové stránky těch příkazů a dal to dohromady sám. Pokud by se na něčem zadrhl, může se znovu zeptat. Takže to „teoretizování“ je záměr.

Navíc spouštět kód, který najdu někde v diskusi na internetu, je dost velká hloupost. Takže nejdřív je potřeba porozumět tomu, co ten kód dělá. A jsem přesvědčený o tom, že můj popis je na porozumění, co je potřeba udělat, snazší, než víš kód.

Jinak nic proti vašemu kódu nemám. Jenom si myslím, že je potřeba znát ty souvislosti – a nemyslím si, že když se někdo ptá, jak má smazat duplicitní soubory, automaticky mu po přečtení vašeho příkau naskočí, že se všechny soubory budou procházet dvakrát a že by tam mohl být problém se speciálními znaky v názvech souborů.

_Jenda

  • *****
  • 1 550
    • Zobrazit profil
    • https://jenda.hrach.eu/
    • E-mail
Re:Smazání souborů se stejným obsahem, ale jiným jménem
« Odpověď #7 kdy: 10. 08. 2021, 19:40:22 »
Pokud by ten adresář obsahoval hodně dat (ať už velké soubory, nebo hodně dat v menších souborech), počítat ty hashe dvakrát nemusí být úplně ideální.
No hlavně je zbytečné počítat hashe u souborů, které mají unikátní velikost. Proto je fdupes tak úžasně rychlý. (možná ještě velké soubory porovnává po kouscích - když se liší začátek, je zbytečné číst dál - ale to nevím)

BoneFlute

  • *****
  • 1 981
    • Zobrazit profil
Re:Smazání souborů se stejným obsahem, ale jiným jménem
« Odpověď #8 kdy: 17. 08. 2021, 15:10:18 »
No hlavně je zbytečné počítat hashe u souborů, které mají unikátní velikost. Proto je fdupes tak úžasně rychlý. (možná ještě velké soubory porovnává po kouscích - když se liší začátek, je zbytečné číst dál - ale to nevím)

Dobrej postřeh! +1

Re:Smazání souborů se stejným obsahem, ale jiným jménem
« Odpověď #9 kdy: 24. 08. 2021, 15:43:40 »
snuff1987

Diky moc, to vypada rozume, snazim se porozumet vsem tem parametrum.

Citace
for i in `sha256sum ./* | awk '{ print $1}'  | uniq -d -w64 `; do  rm -vf `sha256sum ./* | uniq -Dw64 | grep $i | tail +2 | awk '{print $2}'` ;done

 ;D ::)

Neni takto napsany kod pro uplne cely disk (tj. provede akci na uplne celem souborovem systemu, tedy /* ?). Se bojim spustit, aby to nezasahlo cely disk. Vlastne ne, spatne porozumeni kodu, ./* vypada, ze se spusti jen v aktualni slozce.

Soubory nejsou extreme velke, a pocet souboru je v radu nekolika tisicu, vetsinou 2000-15000, vyjimecne vice. Velikost souboru je radove stovky kB, obcas prez 1 MB. Tak by samotne pocitani hashu 2x nebyl takovy problem.

Specialnim nazvum v souborech se snazim vyhnout, celkem se mi to dari redukovat na podtrzitko a alfa-numericke znaky. Ale obcas se mezera, nebo -( a podobne vyskytne. Ale zredukovani tak, aby tam tyto znaky nebyly (jeden z cilu) se mi relativne dari, mozna jeste potreba doladit.

Re:Smazání souborů se stejným obsahem, ale jiným jménem
« Odpověď #10 kdy: 25. 08. 2021, 22:24:25 »
At jsem ruzne zkousel na testovacich datech, vypada to, ze nefunguje navrhovana verze:

Kód: [Vybrat]
for i in `sha256sum ./* | awk '{ print $1}'  | uniq -d -w64 `; do  rm -vf `sha256sum ./* | uniq -Dw64 | grep $i | tail +2 | awk '{print $2}'` ;done

Zkousel jsem ruzna testovaci data, ve slozce s 20 soubory bylo nekolik souboru se stejnym obsahem, ale jinym jmenem, jmena souboru jen z alfa-numerickych znaku. Po spusteni nekolikrat zadny ze souboru smazan nebyl.

Urcite tam ma byt tail +2 ? U nekterych souboru to haze chybu:

Kód: [Vybrat]
tail: cannot open '+2' for reading: No such file or directory

A vypada to, ze chybu hodi tolikrat. kolik je tam ruznych obsahu v mnozine duplicitnich souboru, nehlede na celkovy pocet duplicitnich souboru. tail -2 vybere 2 posledni radky z vyctu, ale tail +2 ? Na textovy soubor mi tail +2 nefunguje, tail -2 vypise posledni dva radky. Verze s tail -2 vymaze nektere duplicitni soubory, ale ne vsechny.

I kdyz se mi puvodne navrzeny kod nepodarilo zprovoznit, snazil jsem se jednotlive veci pochopit a nejak vymyslet vlastni prikaz. Cimz samozrejme dekuji za naznak reseni. A toto je muj vysledek:

Kód: [Vybrat]
for X in `sha256sum ./*  | sort -r | uniq -d -w64 | cut -d "/" -f 2` ; do echo "Mazu duplicitni soubor ${X}" ; rm ${X} ; done

Kod, ktery jsem navrhnul, tak v pripade souboru se stejnym hashem ale jinymi jmeny, vypise abecedne posledni jmeno z listu souborutotozneho obsahu (jinych jmen jinym jmenem), a ten soubor smaze. Od kazde skupiny duplicitnich souboru s unikatnim hashem smaze ten soubor abecedne posledni.

Takze kdyz ma stejny hash-obsah vic nez dva soubory, tak se ten prikaz musi spoustet vicekrat, a to tak dlouho, dokud skript hlasi, ze neco maze (maze jen abecedne posledni soubor). Neprakticke, ale zatim neodladeno. Kdyz skript nic nehlasi-nemaze, tak uz se duplicitni hash nevyskytuje, kazdy hash je unikatni.

Podminkou pro fungovani meho skriptu ale jsou slusne nazvy souboru (bez mezer ci specialnich znaku), jinak si nejsem jisty, co to udela, tak s obecnym pouzitim pozor. V pripade adresaru sha256sum zahlasi, ze hash nepocita - sha256sum: ./Test: Is a directory. A do adresaru se skript nekouka, maze duplicitni soubory jen v danem adresari a v dane urovni podle vseho (ne soubor v adresari a jeho duplicita v podadresari).