1

У меня есть каталог с большим количеством изображений (более 100 000). Многие из них являются дубликатами / идентичными изображениями, но, очевидно, все имеют разные имена файлов. Мне нужно найти изображения, которые имеют наибольшее количество дубликатов в этом каталоге. Например, file1.jpeg содержит 120 дубликатов, file2.jpeg содержит 90 дубликатов и т.д.

Я думал, что я получу md5 каждого файла и сделаю что-то вроде, но я не совсем уверен в деталях. Можно ли это сделать с помощью сценария оболочки?

Чтобы было ясно, мне не нужно удалять дубликаты (пока), мне нужно найти, какие файлы имеют наибольшее количество копий.

Я на OS X, если это поможет.

2 ответа2

1

Это быстрый и грязный конвейер, который будет печатать имена дубликатов между строками дефисов. Он просматривает только текущий каталог, но вы можете использовать find для рекурсивного поиска.

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

Пример вывода:

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

Если файлы являются точными дубликатами, постобработка вывода shasum * | sort может помочь. Сохраните его в файл, поскольку вычисление может занять некоторое время, и оно может понадобиться вам не раз:

shasum * | sort >/tmp/shasums

Например, чтобы увидеть распространение идентичных файлов (только с контрольными суммами, а не именами файлов):

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

Вот способ увидеть имена файлов и количество дубликатов:

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

Без GNU uniq я не могу предложить ничего лучше, чтобы показать имена файлов в хорошем виде, чем следующий скрипт 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(" ", @$_)
        }
    }'

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .