Remove arquivos duplicados comparando-os com MD5 RECURSIVELY

0

Eu quero excluir arquivos duplicados com base no seu valor MD5. Eu já tenho o script abaixo, mas como faço para modificá-lo para que ele funcione recursivamente?

Por exemplo, eu tenho pasta contendo 3 subpastas UMA B C

Eu quero que TODOS esses arquivos em ./ ./A/ ./B/ ./C/ tenham sido verificados no md5 e comparados entre si, se uma correspondência positiva for encontrada, basta excluir aleatoriamente qualquer correspondência. No final, não existem mais duplicatas. Eu não ligo qual correspondência é deletada primeiro.

Espero ter expressado o que preciso para conseguir claramente o suficiente, se não, gentilmente me avise:)

#!/bin/bash
while true
do
  echo "Enter the directory:"
  read directory
  if [ -d $directory ]; then
    break
  else
    echo "Invalid directory"
  fi
done

for FILE in 'ls $directory'
do
  if [ ! -f $FILE ]; then
    break;
  fi
  h='md5sum $directory/$FILE | awk '{ print $1 }''
  for f in 'ls $directory'
  do
    if [ -f $f ] && [ $FILE != $f ]; then
      s='md5sum $directory/$f | awk '{ print $1 }''
      if [ "$s" = "$h" ]; then
        echo Removing $f
        rm -rf $directory/$f
      fi
    fi
  done
done
    
por mandy 02.10.2018 / 12:20

2 respostas

1

Primeiro, uma advertência: assumir a identidade com base em uma soma de verificação é muito perigoso. Não recomendado.

Usar uma soma de verificação como um filtro para remover não-duplicados definidos é OK.

Se eu estivesse fazendo isso, eu me aproximaria assim:

  1. Crie uma lista de arquivos com base no comprimento (comprimento, caminho completo)

  2. Analise essa lista em busca de possíveis tamanhos duplicados.

  3. Quaisquer correspondências são duplicatas possíveis e eu compararia os arquivos suspeitos apropriadamente, se possível.

A razão para usar comprimentos é que esta informação está disponível muito rapidamente sem varrer o arquivo byte-by-by, como é normal nas estatísticas do sistema de arquivos para acesso rápido.

Você pode adicionar outro estágio comparando somas de verificação (em arquivos de tamanho similar) se achar que é mais rápido do que comparar arquivos diretamente, usando uma abordagem semelhante (somas de verificação calculadas uma vez). Use uma abordagem semelhante (comece na lista de comprimentos correspondentes e calcule somas de verificação para essas).

O cálculo da soma de verificação só beneficia você se houver vários arquivos com o mesmo tamanho e, mesmo assim, uma comparação direta byte a byte provavelmente encontrará não correspondências muito rapidamente.

    
por 02.10.2018 / 14:31
0

Eu recomendaria algo como o seguinte:

find . -type f \
    | xargs md5sum \
    | sort -k1,1 \
    | uniq -Dw32

Isso listará todos os arquivos duplicados em grupos de arquivos que tenham um hash MD5 idêntico.

Cuidado, porque o argumento -w32 para uniq só compara os primeiros 32 caracteres ... se você alterar a duração do hash, será necessário atualizar isso.

Considere a seguinte árvore, com o seguinte conteúdo:

./a/1: foo
./a/2: bar
./b/3: hello world
./b/d/5: bar
./c/4: foo
$ find . -type f \
>     | xargs md5sum \
>     | sort -k1,1 \
>     | uniq -Dw32
c157a79031e1c40f85931829bc5fc552  ./a/2
c157a79031e1c40f85931829bc5fc552  ./b/d/5
d3b07384d113edec49eaa6238ad5ff00  ./a/1
d3b07384d113edec49eaa6238ad5ff00  ./c/4

Agora você pode processar as linhas uma a uma ... cada linha com um hash correspondente nos pontos da frente em um arquivo que pode ser duplicado.

Se você não está muito preocupado com qual arquivo é excluído, algo assim funciona:

find . -type f \
    | xargs md5sum \
    | sort -k1,1 \
    | uniq -Dw32 \
    | while read hash file; do 
        [ "${prev_hash}" == "${hash}" ] && rm -v "${file}"
        prev_hash="${hash}"; 
    done

Observe que o MD5 não é mais considerado seguro ... por isso, se você estiver usando isso em um sistema onde os usuários têm controle de arquivos, é possível que eles projetem uma colisão - e, portanto, você remova acidentalmente um arquivo legítimo / de destino em vez de desduplicar como esperava. Prefira um hash mais strong como SHA-256 .

    
por 02.10.2018 / 15:47