Trova file duplicati


90

È possibile trovare file duplicati sul mio disco identici bit per bit ma con nomi file diversi?


3
Nota che ogni possibile metodo per farlo dovrà inevitabilmente confrontare ogni singolo file sul tuo sistema con ogni altro singolo file . Quindi ci vorrà molto tempo, anche quando si prendono scorciatoie.
Shadur,

4
@Shadur se uno è ok con checksum, si riduce a confrontare solo gli hash - che sulla maggior parte dei sistemi è dell'ordine di 10 ^ (5 + -1) di solito <64 byte. Certo, devi leggere i dati almeno una volta. :)
peterph

15
@Shadur Non è vero. È possibile ridurre il tempo controllando la corrispondenza di st_sizes, eliminando quelli con solo uno degli stessi e quindi calcolando solo md5sums per la corrispondenza di st_sizes.
Chris Down,

6
@Shadur anche un approccio incredibilmente sciocco che non consente alcuna operazione di hash potrebbe farlo in Θ (n log n) confronti - non Θ (n²) - usando uno qualsiasi dei diversi algoritmi di ordinamento (basato sul contenuto del file).
derobert,

1
@ChrisDown Sì, la corrispondenza delle dimensioni sarebbe una delle scorciatoie che avevo in mente.
Shadur,

Risposte:


104

fdupespuò fare questo. Da man fdupes:

Cerca nel percorso indicato file duplicati. Tali file si trovano confrontando le dimensioni dei file e le firme MD5, seguite da un confronto byte per byte.

In Debian o Ubuntu, puoi installarlo con apt-get install fdupes. In Fedora / Red Hat / CentOS, puoi installarlo con yum install fdupes. Su Arch Linux si può usare pacman -S fdupes, e su Gentoo, emerge fdupes.

Per eseguire un controllo discendente dalla radice del tuo filesystem, che probabilmente richiederà una quantità significativa di tempo e memoria, usa qualcosa di simile fdupes -r /.

Come richiesto nei commenti, è possibile ottenere i duplicati più grandi nel modo seguente:

fdupes -r . | {
    while IFS= read -r file; do
        [[ $file ]] && du "$file"
    done
} | sort -n

Questo si interromperà se i nomi dei file contengono nuove righe.


Grazie. Come posso filtrare il duplicato più grande? Come posso rendere leggibili le dimensioni umane?
studente

@student: usa qualcosa lungo la linea di (assicurati che fdupes produca solo i nomi dei file senza ulteriori informazioni, o taglia o sed per mantenerlo): fdupes ....... | xargs ls -alhd | egrep 'M |G 'per mantenere i file in formato leggibile da Human e solo quelli con dimensioni in Megabyte o Gigabyte. Modificare il comando in base alle uscite reali.
Olivier Dulac il

2
@OlivierDulac Non dovresti mai analizzare ls . Di solito è peggio del tuo caso d'uso, ma anche nel tuo caso d'uso, rischi di falsi positivi.
Chris Down,

@student - Una volta che hai i nomi dei file, ti verrà duinviato il pipe sort.
Chris Down,

@ChrisDown: è vero che è una cattiva abitudine e può dare falsi positivi. Ma in quel caso (uso interattivo, e solo per visualizzazione, nessuna "rm" o qualcosa del genere che si basa direttamente su di essa) va bene e velocemente ^^. Adoro quelle pagine a cui ti colleghi, tra l'altro (le leggo da qualche mese e sono piene di molte informazioni utili)
Olivier Dulac,

26

Un altro buon strumento è fslint:

fslint è un set di strumenti per trovare vari problemi con i filesystem, inclusi file duplicati e nomi di file problematici ecc.

Sono disponibili singoli strumenti da riga di comando oltre alla GUI e per accedervi, è possibile cambiare o aggiungere a $ PATH la directory / usr / share / fslint / fslint su un'installazione standard. Ognuno di questi comandi in quella directory ha un'opzione --help che dettaglia ulteriormente i suoi parametri.

   findup - find DUPlicate files

Su sistemi basati su Debian, è possibile installarlo con:

sudo apt-get install fslint

Puoi anche farlo manualmente se non vuoi o non puoi installare strumenti di terze parti. Il modo in cui la maggior parte di questi programmi funziona è calcolando i checksum dei file . I file con lo stesso md5sum contengono quasi certamente esattamente gli stessi dati. Quindi, potresti fare qualcosa del genere:

find / -type f -exec md5sum {} \; > md5sums
gawk '{print $1}' md5sums | sort | uniq -d > dupes
while read d; do echo "---"; grep $d md5sums | cut -d ' ' -f 2-; done < dupes 

Output di esempio (i nomi dei file in questo esempio sono gli stessi, ma funzionerà anche quando sono diversi):

$ while read d; do echo "---"; grep $d md5sums | cut -d ' ' -f 2-; done < dupes 
---
 /usr/src/linux-headers-3.2.0-3-common/include/linux/if_bonding.h
 /usr/src/linux-headers-3.2.0-4-common/include/linux/if_bonding.h
---
 /usr/src/linux-headers-3.2.0-3-common/include/linux/route.h
 /usr/src/linux-headers-3.2.0-4-common/include/linux/route.h
---
 /usr/src/linux-headers-3.2.0-3-common/include/drm/Kbuild
 /usr/src/linux-headers-3.2.0-4-common/include/drm/Kbuild
---

Questo sarà molto più lento degli strumenti dedicati già menzionati, ma funzionerà.


4
Sarebbe molto, molto più veloce trovare qualsiasi file con le stesse dimensioni di un altro file usando st_size, eliminando quelli che hanno solo un file di queste dimensioni e quindi calcolando md5sums solo tra file con lo stesso st_size.
Chris Down,

@ChrisDown sì, volevo solo mantenerlo semplice. Naturalmente, ciò che suggerirai accelererà notevolmente le cose. Ecco perché ho il disclaimer sul fatto che sia lento alla fine della mia risposta.
terdon

8

Risposta breve: si.

Versione più lunga: dai un'occhiata alla voce fdupes di wikipedia, sfoggia un bel elenco di soluzioni già pronte. Naturalmente si può scrivere il proprio, non è che le difficoltà - i programmi di hashing come diff, sha*sum, find, sorte uniqdovrebbe fare il lavoro. Puoi persino metterlo su una riga e sarà ancora comprensibile.


6

Se ritieni che una funzione hash (qui MD5) sia esente da collisioni sul tuo dominio:

find $target -type f -exec md5sum '{}' + | sort | uniq --all-repeated --check-chars=32 \
 | cut --characters=35-

Vuoi raggruppare nomi di file identici? Scrivi un semplice script not_uniq.shper formattare l'output:

#!/bin/bash

last_checksum=0
while read line; do
    checksum=${line:0:32}
    filename=${line:34}
    if [ $checksum == $last_checksum ]; then
        if [ ${last_filename:-0} != '0' ]; then
            echo $last_filename
            unset last_filename
        fi
        echo $filename
    else
        if [ ${last_filename:-0} == '0' ]; then
            echo "======="
        fi
        last_filename=$filename
    fi

    last_checksum=$checksum
done

Quindi modifica il findcomando per utilizzare il tuo script:

chmod +x not_uniq.sh
find $target -type f -exec md5sum '{}' + | sort | not_uniq.sh

Questa è un'idea di base. Probabilmente dovresti cambiare findse i nomi dei tuoi file contengono alcuni caratteri. (ad es. spazio)


6

Ho pensato di aggiungere una recente fork migliorata di fdupes, jdupes , che promette di essere più veloce e più ricca di funzionalità rispetto a fdupes (ad es. Filtro dimensioni):

jdupes . -rS -X size-:50m > myjdups.txt

Ciò troverà ricorsivamente file duplicati di dimensioni superiori a 50 MB nella directory corrente e produrrà l'elenco dei risultati in myjdups.txt.

Nota, l'output non è ordinato per dimensione e poiché sembra non essere integrato, ho adattato la risposta di @Chris_Down sopra per ottenere questo:

jdupes -r . -X size-:50m | {
    while IFS= read -r file; do
        [[ $file ]] && du "$file"
    done
} | sort -n > myjdups_sorted.txt

Nota: l'ultima versione di jdupes supporta la corrispondenza dei file con solo un hash parziale invece di attendere l'hash del tutto. Molto utile. (Devi clonare l'archivio git per ottenerlo.) Ecco l'opzione che sto usando in questo momento: jdupes -r -T -T --exclude = size-: 50m --nohidden
Benjamin

2

Wikipedia aveva un articolo ( http://en.wikipedia.org/wiki/List_of_duplicate_file_finders ), con un elenco di software open source disponibile per questa attività, ma ora è stato eliminato .

Aggiungerò che la versione della GUI di fslint è molto interessante, consentendo di usare la maschera per selezionare quali file eliminare. Molto utile per pulire le foto duplicate.

Su Linux puoi usare:

- FSLint: http://www.pixelbeat.org/fslint/

- FDupes: https://en.wikipedia.org/wiki/Fdupes

- DupeGuru: https://www.hardcoded.net/dupeguru/

Gli ultimi 2 lavori su molti sistemi (Windows, Mac e Linux) non ho verificato per FSLint


5
È meglio fornire informazioni effettive qui e non solo un collegamento, il collegamento potrebbe cambiare e quindi la risposta non ha più valore
Anthon

2
La pagina di Wikipedia è vuota.
ihor_dvoretskyi,

si, è stato ripulito, che scossa di pietà ...
MordicusEtCubitus,

L'ho modificato con questi 3 strumenti
MordicusEtCubitus il

0

Ecco la mia opinione su questo:

find -type f -size +3M -print0 | while IFS= read -r -d '' i; do
  echo -n '.'
  if grep -q "$i" md5-partial.txt; then echo -e "\n$i  ---- Already counted, skipping."; continue; fi
  MD5=`dd bs=1M count=1 if="$i" status=noxfer | md5sum`
  MD5=`echo $MD5 | cut -d' ' -f1`
  if grep "$MD5" md5-partial.txt; then echo "\n$i  ----   Possible duplicate"; fi
  echo $MD5 $i >> md5-partial.txt
done

È diverso in quanto esegue l'hashing solo fino ai primi 1 MB del file.
Questo ha alcuni problemi / caratteristiche:

  • Potrebbe esserci una differenza dopo i primi 1 MB, quindi il risultato è piuttosto un candidato da verificare. Potrei risolverlo più tardi.
  • Il controllo in base alla dimensione del file potrebbe accelerare questo.
  • Accetta solo file di dimensioni superiori a 3 MB.

Lo uso per confrontare i video clip quindi questo è abbastanza per me.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.