Como encontrar os arquivos mais comuns ou frequentes no diretório?

Como encontrar os arquivos mais comuns ou frequentes no diretório?

Eu tenho um diretório com muitas imagens (mais de 100.000). Muitas delas são imagens duplicadas/idênticas, mas obviamente todas têm nomes de arquivos diferentes. Preciso encontrar as imagens que possuem mais duplicatas neste diretório. Por exemplo, file1.jpeg tem 120 duplicatas, file2.jpeg tem 90 duplicatas, etc.

Eu estava pensando em pegar o md5 de cada arquivo e fazer algum tipo de coisa, mas estou confuso nos detalhes. Isso pode ser feito com um script de shell?

Para deixar claro, não preciso remover duplicatas (ainda), preciso descobrir quais arquivos têm mais cópias.

Estou no OS X, se isso ajudar.

Responder1

Se os arquivos forem duplicatas exatas, o pós-processamento da saída shasum * | sortprovavelmente ajudará. Salve-o em um arquivo, pois o cálculo pode demorar um pouco e você provavelmente precisará dele mais de uma vez:

shasum * | sort >/tmp/shasums

Por exemplo, para ver a distribuição de arquivos idênticos (apenas com somas de verificação, não com nomes de arquivos):

</tmp/shasums cut -d ' ' -f 1 | uniq -c

Esta é uma maneira de ver os nomes dos arquivos e as contagens duplicadas:

</tmp/shasums sed 's/ .*//' | uniq -c - | join -1 2 - /tmp/shasums | sort -k 2,1

Sem o GNU uniq, não tenho nada melhor a oferecer para mostrar os nomes dos arquivos de uma maneira agradável do que o seguinte script Perl:

</tmp/shasums perl -lne '
    s/^([^ ]*?)  //; # set $1 to the checksum and $2 to the filename
    push @{$names{$1}}, $_; # dispatch file names by checksum
    END {
        # iterate through the checksums, sorted by repeat count
        foreach (sort {@$a <=> @$b} values %names) {
            # print the repeat count and the file names
            printf "%d %s\n", scalar(@$_), join(" ", @$_)
        }
    }'

Responder2

Este é um pipeline rápido e sujo que imprimirá nomes de duplicatas entre linhas de hífens. Ele procura apenas no diretório atual, mas você pode usar findpara fazer uma pesquisa recursiva.

md5sum *.jpeg | sort | awk '{if ($1 != prev) print "-----"; print $2; prev = $1}'

Exemplo de saída:

-----
unique1.jpeg
-----
dup1.jpeg
dup2.jpeg
dup3.jpeg
-----
same1.jpeg
same2.jpeg
-----
solo1.jpeg

informação relacionada