Encontre arquivos duplicados

90

É possível encontrar arquivos duplicados no meu disco que sejam um pouco idênticos, mas que tenham nomes de arquivos diferentes?

aluna
fonte
3
Observe que qualquer método possível para fazer isso precisará, invariavelmente, comparar todos os arquivos em seu sistema com todos os outros arquivos . Portanto, isso levará muito tempo, mesmo ao usar atalhos.
Shadur
4
@Shadur, se alguém estiver de acordo com as somas de verificação, tudo se resume a comparar apenas os hashes - que na maioria dos sistemas é da ordem de 10 ^ (5 + -1), geralmente <entradas de 64 bytes. Obviamente, você precisa ler os dados pelo menos uma vez. :)
peterph
15
@ Shahadur Isso não é verdade. Você pode reduzir o tempo verificando st_sizes correspondentes , eliminando aqueles com apenas um dos mesmos e calculando apenas md5sums para st_sizes correspondentes .
Chris Baixo
6
O @Shadur, mesmo uma abordagem incrivelmente tola, que não permitir operações de hash, poderia fazer isso em Θ (n log n), em comparação - e não (n²) - usando qualquer um dos vários algoritmos de classificação (com base no conteúdo do arquivo).
Derobert # 04/13
1
@ ChrisDown Sim, a correspondência de tamanho seria um dos atalhos que eu tinha em mente.
Shadur

Respostas:

104

fdupesposso fazer isso. De man fdupes:

Pesquisa o caminho especificado para arquivos duplicados. Esses arquivos são encontrados pela comparação de tamanhos de arquivo e assinaturas MD5, seguidos por uma comparação de byte a byte.

No Debian ou Ubuntu, você pode instalá-lo com apt-get install fdupes. No Fedora / Red Hat / CentOS, você pode instalá-lo yum install fdupes. No Arch Linux você pode usar pacman -S fdupes, e no Gentoo emerge fdupes,.

Para executar uma verificação descendente da raiz do sistema de arquivos, que provavelmente levará uma quantidade significativa de tempo e memória, use algo como fdupes -r /.

Conforme solicitado nos comentários, você pode obter as maiores duplicatas fazendo o seguinte:

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

Isso será interrompido se seus nomes de arquivos contiverem novas linhas.

Chris Down
fonte
Obrigado. Como posso filtrar o maior dupe? Como posso tornar os tamanhos legíveis por humanos?
estudante de
@ aluno: use algo ao longo da linha de (certifique-se de que o fdupes apenas exiba os nomes dos arquivos sem informações adicionais, ou corte ou sed para manter isso): fdupes ....... | xargs ls -alhd | egrep 'M |G 'para manter os arquivos em formato legível por seres humanos e somente aqueles com tamanho em megabytes ou gigabytes. Mude o comando para se adequar às saídas reais.
Olivier Dulac
2
@OlivierDulac Você nunca deve analisar ls . Geralmente é pior que o seu caso de uso, mas mesmo no seu caso de uso, você corre o risco de falsos positivos.
Chris Baixo
@ aluno - Depois de ter os nomes dos arquivos, o ducanal sortserá direcionado a você.
Chris Baixo
@ ChrisDown: é verdade que é um mau hábito e pode dar falsos positivos. Mas nesse caso (uso interativo e apenas para exibição, nenhum "rm" ou qualquer coisa do tipo que depende diretamente dele) é bom e rápido ^^. Eu amo essas páginas que apontam para, btw (foi lê-los desde há alguns meses, e cheio de muitas informações sobre uteis)
Olivier Dulac
26

Outra boa ferramenta é fslint:

O fslint é um conjunto de ferramentas para encontrar vários problemas com sistemas de arquivos, incluindo arquivos duplicados e nomes de arquivos problemáticos etc.

Ferramentas de linha de comando individuais estão disponíveis além da GUI e, para acessá-las, é possível mudar ou adicionar ao $ PATH o diretório / usr / share / fslint / fslint em uma instalação padrão. Cada um desses comandos nesse diretório possui uma opção --help, que detalha mais detalhadamente seus parâmetros.

   findup - find DUPlicate files

Em sistemas baseados em debian, você pode instalá-lo com:

sudo apt-get install fslint

Você também pode fazer isso manualmente se não desejar ou não puder instalar ferramentas de terceiros. A maneira como a maioria desses programas funciona é calculando as somas de verificação de arquivos . Arquivos com o mesmo md5sum quase certamente contêm exatamente os mesmos dados. Então, você poderia fazer algo assim:

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 

Saída de amostra (os nomes de arquivo neste exemplo são os mesmos, mas também funcionará quando forem 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
---

Isso será muito mais lento que as ferramentas dedicadas já mencionadas, mas funcionará.

terdon
fonte
4
Seria muito, muito mais rápido encontrar qualquer arquivo com o mesmo tamanho que outro arquivo st_size, eliminando qualquer arquivo que tenha apenas um arquivo desse tamanho e calculando o md5sums apenas entre arquivos com o mesmo st_size.
Chris Baixo
@ ChrisDown sim, só queria manter as coisas simples. O que você sugere irá acelerar bastante as coisas, é claro. É por isso que tenho a isenção de responsabilidade por ser lenta no final da minha resposta.
terdon
8

Resposta curta: sim.

Versão mais longa: dê uma olhada na entrada wikipedia fdupes , que ostenta uma lista bastante agradável de soluções prontas. Claro que você pode escrever seu próprio, não é que difícil - programas de hashing como diff, sha*sum, find, sorte uniqdeve fazer o trabalho. Você pode até colocá-lo em uma linha e ainda será compreensível.

peterph
fonte
6

Se você acredita que uma função de hash (aqui MD5) está livre de colisões no seu domínio:

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

Deseja nomes de arquivos idênticos agrupados? Escreva um script simples not_uniq.shpara formatar a saída:

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

Então mude o findcomando para usar seu script:

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

Essa é uma ideia básica. Provavelmente você deve mudar findse os nomes dos seus arquivos contiverem alguns caracteres. (por exemplo, espaço)

xin
fonte
6

Eu pensei em adicionar um fork melhorado recente de fdupes, jdupes , que promete ser mais rápido e mais rico em recursos do que os fdupes (por exemplo, filtro de tamanho):

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

Isso encontrará recursivamente arquivos duplicados maiores que 50 MB no diretório atual e produzirá a lista resultante em myjdups.txt.

Observe que a saída não é classificada por tamanho e, como parece não ser incorporada, adaptei a resposta @Chris_Down acima para conseguir isso:

jdupes -r . -X size-:50m | {
    while IFS= read -r file; do
        [[ $file ]] && du "$file"
    done
} | sort -n > myjdups_sorted.txt
Sebastian Müller
fonte
Nota: a versão mais recente do jdupes suporta arquivos correspondentes com apenas um hash parcial, em vez de esperar o hash completo. Muito útil. (Você precisa clonar o arquivo git para obtê-lo.) Aqui está a opção que estou usando agora: jdupes -r -T -T --exclude = size-: 50m --nohidden
Benjamin
2

A Wikipedia tinha um artigo ( http://en.wikipedia.org/wiki/List_of_duplicate_file_finders ), com uma lista de softwares de código aberto disponíveis para esta tarefa, mas agora foi excluído .

Acrescentarei que a versão GUI do fslint é muito interessante, permitindo usar a máscara para selecionar os arquivos a serem excluídos. Muito útil para limpar fotos duplicadas.

No Linux você pode usar:

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

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

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

Os 2 últimos trabalhos em muitos sistemas (windows, mac e linux) não verifiquei o FSLint

MordicusEtCubitus
fonte
5
É melhor fornecer informações reais aqui e não apenas um link, o link pode mudar e a resposta não tem mais valor
Anthon
2
A página da Wikipedia está vazia.
Ihor_dvoretskyi 10/09/2015
sim, foi limpo, que pena ...
MordicusEtCubitus /
Eu o editei com essas três ferramentas #
MordicusEtCubitus
0

Aqui está a minha opinião sobre isso:

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

É diferente, pois apenas hashes até 1 MB do arquivo.
Isso tem alguns problemas / recursos:

  • Pode haver uma diferença após os primeiros 1 MB, portanto o resultado é um candidato a ser verificado. Eu posso consertar isso mais tarde.
  • A verificação pelo tamanho do arquivo primeiro pode acelerar isso.
  • Leva apenas arquivos maiores que 3 MB.

Eu o uso para comparar clipes de vídeo, então isso é suficiente para mim.

Ondra Žižka
fonte