Cómo eliminar archivos duplicados usando bash

10

Tengo una carpeta con archivos duplicados (por md5sum( md5en una Mac)) y quiero tener un trabajo programado para eliminar cualquier encontrado.

Sin embargo, estoy atascado en cómo hacer esto. Lo que tengo hasta ahora:

md5 -r * | sort

Lo que genera algo como esto:

04c5d52b7acdfbecd5f3bdd8a39bf8fb gordondam_en-au11915031300_1366x768.jpg
1e88c6899920d2c192897c886e764fc2 fortbourtange_zh-cn9788197909_1366x768.jpg
266ea304b15bf4a5650f95cf385b16de nebraskasupercell_fr-fr11286079811_1366x768.jpg
324735b755c40d332213899fa545c463 grossescheidegg_en-us10868142387_1366x768.jpg
3993028fcea692328e097de50b26f540 Soyuz Spacecraft Rolled Out For Launch of One Year Crew.png
677bcd6006a305f4601bfb27699403b0 lechaustria_zh-cn7190263094_1366x768.jpg
80d03451b88ec29bff7d48f292a25ce6 ontariosunrise_en-ca10284703762_1366x768.jpg
b6d9d24531bc62d2a26244d24624c4b1 manateeday_row10617199289_1366x768.jpg
ca1486dbdb31ef6af83e5a40809ec561 Grueling Coursework.jpg
cdf26393577ac2a61b6ce85d22daed24 Star trails over Mauna Kea.jpg
dc3ad6658d8f8155c74054991910f39c smoocave_en-au10358472670_1366x768.jpg
dc3ad6658d8f8155c74054991910f39c smoocave_en-au10358472670_1366x7682.jpg

¿Cómo puedo procesar según el MD5 del archivo para eliminar duplicados? Realmente no me importa qué "original" conserve, pero solo quiero conservar uno.

¿Debería abordar esto de una manera diferente?

madriguera
fuente
3
Ya hay un fdupescomando que hará esto ... No estoy seguro de en qué distribución estás, pero está en un paquete Debian con el mismo nombre. Además, MD5 es un hash bastante débil hoy en día; probablemente desee usar sha256sum o mejor sha512sum(que en realidad debería ser más rápido en hardware de PC normal)
derobert
1
@derobert - Sé que MD5 es un hash débil, pero es simple y lo suficientemente bueno para comparar archivos pequeños :)
warren
bueno, las colisiones MD5 son conocidas y pueden generarse con cantidades bastante modestas de potencia de CPU, y hay un comando que puede sustituir para usar SHA-512, así que ...
derobert
@derobert - Entiendo que hay potenciales negativos al usar md5 ... pero es más que adecuado en este escenario (queriendo asegurarme de que no tengo archivos duplicados en un directorio dado)
warren
1
Lo suficientemente justo. El punto principal del comentario fue señalar fdupes.
derobert

Respuestas:

3

Estoy trabajando en Linux, lo que significa que es el comando md5sumque genera:

> md5sum *
d41d8cd98f00b204e9800998ecf8427e  file_1
d41d8cd98f00b204e9800998ecf8427e  file_10
d41d8cd98f00b204e9800998ecf8427e  file_2
d41d8cd98f00b204e9800998ecf8427e  file_3
d41d8cd98f00b204e9800998ecf8427e  file_4
d41d8cd98f00b204e9800998ecf8427e  file_5
d41d8cd98f00b204e9800998ecf8427e  file_6
d41d8cd98f00b204e9800998ecf8427e  file_7
d41d8cd98f00b204e9800998ecf8427e  file_8
d41d8cd98f00b204e9800998ecf8427e  file_9
b026324c6904b2a9cb4b88d6d61c81d1  other_file_1
31d30eea8d0968d6458e0ad0027c9f80  other_file_10
26ab0db90d72e28ad0ba1e22ee510510  other_file_2
6d7fce9fee471194aa8b5b6e47267f03  other_file_3
48a24b70a0b376535542b996af517398  other_file_4
1dcca23355272056f04fe8bf20edfce0  other_file_5
9ae0ea9e3c9c6e1b9b6252c8395efdc1  other_file_6
84bc3da1b3e33a18e8d5e1bdd7a18d7a  other_file_7
c30f7472766d25af1dc80b3ffc9a58c7  other_file_8
7c5aba41f53293b712fd86d08ed5b36e  other_file_9

Ahora usando awky xargsel comando sería:

md5sum * | \
sort | \
awk 'BEGIN{lasthash = ""} $1 == lasthash {print $2} {lasthash = $1}' | \
xargs rm

La awkparte se inicializa lasthashcon la cadena vacía, que no coincidirá con ningún hash, y luego verifica para cada línea si el hash in lasthashes el mismo que el hash (primera columna) del archivo actual (segunda columna). Si es así, lo imprime. Al final de cada paso, se establecerá lasthashen el hash del archivo actual (puede limitar esto para que solo se configure si los hashes son diferentes, pero eso debería ser algo menor, especialmente si no tiene muchos archivos coincidentes). Los nombres de archivo que awk escupe se alimentan rmcon xargs, lo que básicamente llama rmcon lo que la awkparte nos da.

Probablemente necesite filtrar directorios antes md5sum *.

Editar:

Usando el método Marcins también puedes usar este:

comm -1 -2 \
  <(ls) | \
  <(md5sum * | \
    sort -k1 | \
    uniq -w 32 | \
    awk '{print $2}' | \
    sort) \
xargs rm

Esto resta de la lista de archivos obtenida por lsel primer nombre de archivo de cada hash único obtenido por md5sum * | sort -k1 | uniq -w 32 | awk '{print $2}'.

Tristan Storch
fuente
1
gracias: md5 -r * | sort -t ' ' -k 4 -r | awk 'BEGIN{lasthash = ""} $1 == lasthash {print $2} {lasthash = $1}' | xargs rmes la llamada en OS X (según la sugerencia de @ Stephen Kitt , puse una echo 'will remove 'al final antes de intentarlo rm)
warren
Probablemente deberías editar tu pregunta porque la solución dada no coincide con el resultado de ejemplo que diste.
Stephen Kitt
1
Y deberías cambiarte sort -t ' ' -k 4 -ra sort.
Tristan Storch
@TristanStorch - buen lugar :)
warren
Esto supone que no tiene espacios en sus nombres de archivo, una suposición peligrosa en cualquier circunstancia. (Y especialmente dado que el OP está usando una Mac. Te reto a que encuentres una Mac, cualquier Mac, que no tenga nombres de archivos que contengan espacio). :)
Comodín el
7

Puede identificar archivos duplicados con el siguiente comando:

md5sum * | sort -k1 | uniq -w 32 -d
Marcin
fuente
1
Esto genera solo un archivo para cada conjunto de duplicados. Si desea eliminar todos los duplicados y conservar solo uno, puede conservar los que obtiene con este comando y eliminar el resto
golimar
2

Me encontré con fdupes como respuesta a esta pregunta similar: /superuser/386199/how-to-remove-duplicated-files-in-a-directory

Pude apt-get install fdupesen Ubuntu. Definitivamente querrás leer la página del manual. En mi caso, pude obtener los resultados deseados así:

fdupes -qdN -r /ops/backup/

Lo que dice "mire recursivamente a través de / ops / backup y encuentre todos los archivos duplicados: conserve la primera copia de cualquier archivo dado y elimine silenciosamente el resto". Esto hace que sea muy fácil mantener varios volcados de una base de datos de escritura poco frecuente.

dannyman
fuente
1

Si tiene prisa (o tiene muchos archivos) y quiere evitar la sobrecarga de una especie (lleva tiempo) pero no le importa la sobrecarga de memoria de una tabla hash (o tiene un montón de ram con sus lotes de archivos),

find . -type f -print0 | xargs -0 md5sum | awk 'h[$1]{ printf "%s\0", $2; next }{ h[$1] = $2 }' | xargs -0 rm

find . -type f -print0: Encuentre todos los archivos y envíelos con nombres nulos

xargs -0 md5sum: calcule hashes en paralelo (ajuste -nmax-args y -Pmax-procs como desee, vea man xargs)

awk 'h[$1]{ printf "%s\0", $2; next }{ h[$1] = $2 }': si hay una entrada en la tabla hash awk que contiene el md5sum que estamos viendo actualmente, imprima el nombre del archivo que estamos viendo actualmente, con terminación nula. De lo contrario, agregue el nombre del archivo a la tabla hash.

xargs -0 rm: tome las cadenas terminadas en nulo canalizadas y envíelas a rm.

Esto es mucho más rápido que fdupes.

Si tiene un nombre de archivo que contiene una nueva línea, awk probablemente lo truncará en la nueva línea ya que md5sum también separa los registros por nuevas líneas.

Esto se basa en /programming/11532157/remove-duplicate-lines-without-sorting y /programming/9133315/how-can-i-output-null-terminated- cuerdas en awk

Alex
fuente
1
md5sum * | sort -k1 | uniq -w 32 -d | cut -d' ' -f3 | xargs -I{} sh -c 'rm {}'
  1. tomar todos los valores md5
  2. ordenarlos para que los engaños sean secuenciales para uniq
  3. ejecutar uniq solo para generar duplicados
  4. cortar el nombre de archivo de la línea con el valor md5
  5. repetidamente llame a eliminar en los nombres de archivo
Carter Cole
fuente
0
comm -13 <(md5sum * | sort | uniq -w 32 -d) <(md5sum * | sort | uniq -w 32 -D) | cut -f 3- -d" " | xargs -d '\n' rm

caracteristicas:

  • Aún funciona si hay más de un duplicado por archivo
  • Todavía funciona si los nombres de archivo tienen espacios
  • Todavía funciona si tienes un alias lscon un tipo o--color=always
Alex Lamson
fuente