Encuentra archivos duplicados

91

¿Es posible encontrar archivos duplicados en mi disco que sean bit a bit idénticos pero que tengan nombres de archivo diferentes?

estudiante
fuente
3
Tenga en cuenta que cualquier método posible para hacer esto invariablemente tendrá que comparar cada archivo en su sistema con cada uno de los otros archivos . Por lo tanto, esto llevará mucho tiempo, incluso cuando se toman atajos.
Shadur
44
@Shadur si uno está bien con las sumas de verificación, se reduce a comparar solo los hashes, que en la mayoría de los sistemas es del orden de 10 ^ (5 + -1) generalmente <entradas de 64 bytes. Por supuesto, debe leer los datos al menos una vez. :)
Peter
15
@Shadur Eso no es cierto. Puede reducir el tiempo comprobando si hay st_sizes coincidentes , eliminando aquellos con solo uno de los mismos, y luego calculando solo md5sums para st_sizes s coincidentes .
Chris Down
66
@Shadur, incluso un enfoque increíblemente tonto que no permita cualquier operación de hash podría hacer esto en Θ (n log n) compara, no Θ (n²), usando cualquiera de varios algoritmos de clasificación (basados ​​en el contenido del archivo).
derobert
1
@ChrisDown Sí, la coincidencia de tamaño sería uno de los atajos que tenía en mente.
Shadur

Respuestas:

104

fdupespuede hacer esto De man fdupes:

Busca en la ruta dada archivos duplicados. Dichos archivos se encuentran comparando tamaños de archivo y firmas MD5, seguidos de una comparación byte por byte.

En Debian o Ubuntu, puede instalarlo con apt-get install fdupes. En Fedora / Red Hat / CentOS, puede instalarlo con yum install fdupes. En Arch Linux se puede utilizar pacman -S fdupes, y en Gentoo, emerge fdupes.

Para ejecutar una verificación descendente desde la raíz de su sistema de archivos, que probablemente tomará una cantidad significativa de tiempo y memoria, use algo como fdupes -r /.

Como se preguntó en los comentarios, puede obtener los duplicados más grandes haciendo lo siguiente:

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

Esto se romperá si sus nombres de archivo contienen nuevas líneas.

Chris Down
fuente
Gracias. ¿Cómo puedo filtrar el engaño más grande? ¿Cómo puedo hacer que los tamaños sean legibles por humanos?
estudiante
@student: use algo a lo largo de la línea de (asegúrese de que fdupes solo muestre los nombres de archivo sin información adicional, o corte o sed simplemente para mantener eso): fdupes ....... | xargs ls -alhd | egrep 'M |G 'para mantener los archivos en formato legible para humanos y solo aquellos con tamaño en Megabytes o Gigabytes. Cambie el comando para adaptarse a las salidas reales.
Olivier Dulac
2
@ OlivierDulac Nunca deberías analizar ls . Por lo general, es peor que su caso de uso, pero incluso en su caso de uso, corre el riesgo de falsos positivos.
Chris Down
@student: una vez que tenga los nombres de archivo, ducanalizado a sortle dirá.
Chris Down
@ChrisDown: es cierto que es un mal hábito y puede dar falsos positivos. Pero en ese caso (uso interactivo, y solo para visualización, sin "rm" o cualquier cosa del tipo que dependa directamente de él) está bien y rápido ^^. Me encantan esas páginas a las que enlazas, por cierto (las he estado leyendo desde hace unos meses y están llenas de muchas informaciones útiles)
Olivier Dulac
27

Otra buena herramienta es fslint:

fslint es un conjunto de herramientas para encontrar varios problemas con los sistemas de archivos, incluidos archivos duplicados y nombres de archivos problemáticos, etc.

Las herramientas de línea de comandos individuales están disponibles además de la GUI y para acceder a ellas, se puede cambiar o agregar a $ PATH el directorio / usr / share / fslint / fslint en una instalación estándar. Cada uno de estos comandos en ese directorio tiene una opción --help que detalla más sus parámetros.

   findup - find DUPlicate files

En sistemas basados ​​en Debian, puede instalarlo con:

sudo apt-get install fslint

También puede hacerlo manualmente si no desea o no puede instalar herramientas de terceros. La mayoría de los programas funcionan calculando sumas de comprobación de archivos . Los archivos con el mismo md5sum casi seguramente contienen exactamente los mismos datos. Entonces, podrías hacer algo como esto:

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 

Salida de muestra (los nombres de archivo en este ejemplo son los mismos, pero también funcionarán cuando sean diferentes):

$ 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
---

Esto será mucho más lento que las herramientas dedicadas ya mencionadas, pero funcionará.

terdon
fuente
44
Sería mucho, mucho más rápido encontrar archivos con el mismo tamaño que otro archivo st_size, eliminando cualquiera que solo tenga un archivo de este tamaño y luego calculando md5sums solo entre archivos con el mismo st_size.
Chris Down
@ChrisDown sí, solo quería que sea simple. Lo que sugiera, por supuesto, acelerará enormemente las cosas. Es por eso que tengo el descargo de responsabilidad de que sea lento al final de mi respuesta.
terdon
Se puede ejecutar en macOS, pero debe reemplazar md5sum {}con md5 -q {}y gawk '{print $1}'concat
Finesse
8

Respuesta corta: sí.

Versión más larga: eche un vistazo a la entrada de wikipedia fdupes , tiene una lista bastante buena de soluciones listas para usar . Por supuesto, usted puede escribir su propia, no es que difícil - programas de hash como diff, sha*sum, find, sorty uniqdebe hacer el trabajo. Incluso puede ponerlo en una línea, y seguirá siendo comprensible.

Peterph
fuente
6

Si cree que una función hash (aquí MD5) no tiene colisión en su dominio:

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

¿Quieres nombres de archivo idénticos agrupados? Escriba un script simple not_uniq.shpara formatear la salida:

#!/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

Luego cambie el findcomando para usar su script:

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

Esta es una idea básica. Probablemente debería cambiar findsi sus nombres de archivo contienen algunos caracteres. (por ejemplo, espacio)

xin
fuente
6

Pensé agregar una bifurcación mejorada reciente de fdupes, jdupes , que promete ser más rápida y más rica en funciones que los fdupes (por ejemplo, filtro de tamaño):

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

Esto buscará de forma recursiva archivos duplicados de más de 50 MB en el directorio actual y generará la lista resultante en myjdups.txt.

Tenga en cuenta que el resultado no está ordenado por tamaño y, dado que parece no estar integrado, he adaptado la respuesta @Chris_Down anterior para lograr esto:

jdupes -r . -X size-:50m | {
    while IFS= read -r file; do
        [[ $file ]] && du "$file"
    done
} | sort -n > myjdups_sorted.txt
Sebastian Müller
fuente
Nota: la última versión de jdupes admite archivos coincidentes con solo un hash parcial en lugar de esperar a hacerlo todo. Muy útil. (Debe clonar el archivo git para obtenerlo). Aquí está la opción que estoy usando en este momento: jdupes -r -T -T --exclude = size-: 50m --nohidden
SurpriseDog
2

Wikipedia tenía un artículo ( http://en.wikipedia.org/wiki/List_of_duplicate_file_finders ), con una lista de software de código abierto disponible para esta tarea, pero ahora se ha eliminado .

Agregaré que la versión GUI de fslint es muy interesante, ya que permite usar la máscara para seleccionar qué archivos eliminar. Muy útil para limpiar fotos duplicadas.

En Linux puedes usar:

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

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

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

Los 2 últimos trabajos en muchos sistemas (Windows, Mac y Linux) no he verificado FSLint

MordicusEtCubitus
fuente
55
Es mejor proporcionar información real aquí y no solo un enlace, el enlace puede cambiar y luego la respuesta no tiene valor
Anthon
2
La página de Wikipedia está vacía.
ihor_dvoretskyi
Sí, se ha limpiado, qué pena ...
MordicusEtCubitus
Lo he editado con estas 3 herramientas
MordicusEtCubitus
0

Aquí está mi opinión sobre eso:

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

Es diferente en el sentido de que solo divide hasta el primer 1 MB del archivo.
Esto tiene algunos problemas / características:

  • Puede haber una diferencia después del primer 1 MB, por lo que el resultado es más bien un candidato para verificar. Podría arreglar eso más tarde.
  • Verificar por tamaño de archivo primero podría acelerar esto.
  • Solo toma archivos de más de 3 MB.

Lo uso para comparar videoclips, así que esto es suficiente para mí.

Ondra Žižka
fuente