¿Cómo eliminar archivos duplicados en un directorio?

¿Cómo eliminar archivos duplicados en un directorio?

Descargué muchas imágenes en un directorio.
El descargador cambió el nombre de los archivos que ya existen.
También cambié el nombre de algunos de los archivos manualmente.

a.jpg
b.jpg
b(2).jpg
hello.jpg      <-- manually renamed `b(3).jpg`
c.jpg
c(2).jpg
world.jpg      <-- manually renamed `d.jpg`
d(2).jpg
d(3).jpg

¿Cómo eliminar los duplicados? El resultado debería ser:

a.jpg
b.jpg
c.jpg
world.jpg

nota: el nombre no importa. Sólo quiero archivos uniq.

Respuesta1

fiesta 4.x

#!/bin/bash
declare -A arr
shopt -s globstar

for file in **; do
  [[ -f "$file" ]] || continue
   
  read cksm _ < <(md5sum "$file")
  if ((arr[$cksm]++)); then 
    echo "rm $file"
  fi
done

Esto es recursivo y maneja cualquier nombre de archivo. La desventaja es que requiere la versión 4.x para poder utilizar matrices asociativas y búsqueda recursiva. Elimina el echosi te gustan los resultados.

versión boquiabierta

gawk '
  {
    cmd="md5sum " q FILENAME q
    cmd | getline cksm
    close(cmd)
    sub(/ .*$/,"",cksm)
    if(a[cksm]++){
      cmd="echo rm " q FILENAME q
      system(cmd)
      close(cmd)
    }
    nextfile
  }' q='"' *

Tenga en cuenta que esto aún se interrumpirá en archivos que tengan comillas dobles en su nombre. No hay forma real de solucionar eso awk. Elimina el echosi te gustan los resultados.

Respuesta2

fdupeses la herramienta de tu elección. Para buscar todos los archivos duplicados (por contenido, no por nombre) en el directorio actual:

fdupes -r .

Para confirmar manualmente la eliminación de archivos duplicados:

fdupes -r -d .

Para eliminar automáticamente todas las copias excepto la primera de cada archivo duplicado (tenga cuidado, esta advertencia, esto en realidad elimina archivos, según lo solicitado):

fdupes -r -f . | grep -v '^$' | xargs rm -v

Recomiendo verificar manualmente los archivos antes de eliminarlos:

fdupes -rf . | grep -v '^$' > files
... # check files
xargs -a files rm -v

Respuesta3

recomiendoclones.

Fclones es un moderno buscador y eliminador de archivos duplicados escrito en Rust, disponible en la mayoría de las distribuciones de Linux y macOS.

Características notables:

  • admite espacios, caracteres no ASCII y de control en rutas de archivos
  • permite buscar en múltiples árboles de directorios
  • respeta los archivos .gitignore
  • seguro: permite inspeccionar la lista de duplicados manualmente antes de realizar cualquier acción sobre ellos
  • ofrece muchas opciones para filtrar/seleccionar archivos para eliminar o conservar
  • muy rapido

Para buscar duplicados en el directorio actual simplemente ejecute:

fclones group . >dupes.txt

Luego puedes inspeccionar el dupes.txtarchivo para comprobar si encontró los duplicados correctos (también puedes modificar esa lista a tu gusto).

Finalmente elimine/vincule/mueva los archivos duplicados con uno de:

fclones remove <dupes.txt
fclones link <dupes.txt
fclones move target <dupes.txt
fclones dedupe <dupes.txt   # copy-on-write deduplication on some filesystems

Ejemplo:

pkolaczk@p5520:~/Temp$ mkdir files
pkolaczk@p5520:~/Temp$ echo foo >files/foo1.txt
pkolaczk@p5520:~/Temp$ echo foo >files/foo2.txt
pkolaczk@p5520:~/Temp$ echo foo >files/foo3.txt

pkolaczk@p5520:~/Temp$ fclones group files >dupes.txt
[2022-05-13 18:48:25.608] fclones:  info: Started grouping
[2022-05-13 18:48:25.613] fclones:  info: Scanned 4 file entries
[2022-05-13 18:48:25.613] fclones:  info: Found 3 (12 B) files matching selection criteria
[2022-05-13 18:48:25.614] fclones:  info: Found 2 (8 B) candidates after grouping by size
[2022-05-13 18:48:25.614] fclones:  info: Found 2 (8 B) candidates after grouping by paths and file identifiers
[2022-05-13 18:48:25.619] fclones:  info: Found 2 (8 B) candidates after grouping by prefix
[2022-05-13 18:48:25.620] fclones:  info: Found 2 (8 B) candidates after grouping by suffix
[2022-05-13 18:48:25.620] fclones:  info: Found 2 (8 B) redundant files

pkolaczk@p5520:~/Temp$ cat dupes.txt
# Report by fclones 0.24.0
# Timestamp: 2022-05-13 18:48:25.621 +0200
# Command: fclones group files
# Base dir: /home/pkolaczk/Temp
# Total: 12 B (12 B) in 3 files in 1 groups
# Redundant: 8 B (8 B) in 2 files
# Missing: 0 B (0 B) in 0 files
6109f093b3fd5eb1060989c990d1226f, 4 B (4 B) * 3:
    /home/pkolaczk/Temp/files/foo1.txt
    /home/pkolaczk/Temp/files/foo2.txt
    /home/pkolaczk/Temp/files/foo3.txt

pkolaczk@p5520:~/Temp$ fclones remove <dupes.txt
[2022-05-13 18:48:41.002] fclones:  info: Started deduplicating
[2022-05-13 18:48:41.003] fclones:  info: Processed 2 files and reclaimed 8 B space

pkolaczk@p5520:~/Temp$ ls files
foo1.txt

Respuesta4

¿Cómo probar archivos que tienen contenido único?

if diff "$file1" "$file2" > /dev/null; then
    ...

¿Cómo podemos obtener una lista de archivos en el directorio?

files="$( find ${files_dir} -type f )"

Podemos obtener 2 archivos cualesquiera de esa lista y verificar si sus nombres son diferentes y su contenido es el mismo.

#!/bin/bash
# removeDuplicates.sh

files_dir=$1
if [[ -z "$files_dir" ]]; then
    echo "Error: files dir is undefined"
fi

files="$( find ${files_dir} -type f )"
for file1 in $files; do
    for file2 in $files; do
        # echo "checking $file1 and $file2"
        if [[ "$file1" != "$file2" && -e "$file1" && -e "$file2" ]]; then
            if diff "$file1" "$file2" > /dev/null; then
                echo "$file1 and $file2 are duplicates"
                rm -v "$file2"
            fi
        fi
    done
done

Por ejemplo, tenemos algún directorio:

$> ls .tmp -1
all(2).txt
all.txt
file
text
text(2)

Entonces solo hay 3 archivos únicos.

Ejecutemos ese script:

$> ./removeDuplicates.sh .tmp/
.tmp/text(2) and .tmp/text are duplicates
removed `.tmp/text'
.tmp/all.txt and .tmp/all(2).txt are duplicates
removed `.tmp/all(2).txt'

Y solo nos quedan 3 archivos.

$> ls .tmp/ -1
all.txt
file
text(2)

información relacionada