Найдите все дублирующиеся файлы по MD5-хешу.

Вопрос или проблема

Я пытаюсь найти все дублирующиеся файлы (по хешу MD5) и отсортировать их по размеру файла. Пока у меня есть следующее:

find . -type f -print0 | xargs -0 -I "{}" sh -c 'md5sum "{}" |  cut -f1 -d " " | tr "\n" " "; du -h "{}"' | sort -h -k2 -r | uniq -w32 --all-repeated=separate

Вывод этого выглядит так:

1832348bb0c3b0b8a637a3eaf13d9f22 4.0K   ./picture.sh
1832348bb0c3b0b8a637a3eaf13d9f22 4.0K   ./picture2.sh
1832348bb0c3b0b8a637a3eaf13d9f22 4.0K   ./picture2.s

d41d8cd98f00b204e9800998ecf8427e 0      ./test(1).log

Это самый эффективный способ?

Из xargs(1):

-I replace-str
… Предполагает -x и -L 1.

Так что это не самый эффективный способ. Было бы более эффективно, если бы вы просто передали как можно больше имен файлов в md5sum, что будет:

find . -type f -print0 | xargs -0 md5sum | sort | uniq -w32 --all-repeated=separate

В качестве альтернативы xargs можно использовать (GNU) find(1) -exec (обратите внимание на знак плюс)

-exec command {} +

Командная строка строится аналогично тому, как xargs строит свои командные строки.


С этими альтернативами у вас, конечно, не будет размера файла. Если вам действительно нужен размер файла, создайте shell-скрипт, который выполняет md5sum и du -h и объединяет строки с помощью join.

Иногда мы работаем с сокращенными наборами команд linux, такими как busybox или другими инструментами, которые идут с NAS и другими встраиваемыми Linux-устройствами (IoT). В этих случаях мы не можем использовать такие опции, как -print0, из-за проблем с пространствами имен. Поэтому мы можем предпочесть вместо этого:

find | while read file; do md5sum "$file"; done > /destination/file

Тогда наш /destination/file готов для любого рода обработки, такой как sort и uniq, как обычно.

Используйте либо btrfs + duperemove, либо zfs с онлайн-дедупликацией. Это работает на уровне файловой системы и будет сопоставлять даже равные части файлов, а затем использовать CoW файловой системы, чтобы оставить только одну из каждой, сохраняя файлы на месте. Когда вы изменяете одну из общих частей в одном из файлов, она будет записывать изменение отдельно. Таким образом, вы можете иметь такие вещи, как /media и /backup/media-2017-01-01, которые потребляют только размер каждой уникальной части информации в обоих деревьях.

Или вы можете использовать fdupes:

fdupes -R /usr/share/doc | while read name; do \
    test -n "$name" && \
    size=`stat -c %s "$name" 2>/dev/null` && \
    echo "$size  $name"; \
done | sort -n

Ответ или решение

Чтобы выявить все дубликаты файлов на основе MD5-хеша и отсортировать их по размеру, можно использовать несколько подходов. Описание вашей текущей команды заслуживает того, чтобы его проанализировать и оптимизировать. Рассмотрим несколько методов, которые можно использовать для этой задачи.

Анализ текущего подхода

Ваша команда выглядит следующим образом:

find . -type f -print0 | xargs -0 -I "{}" sh -c 'md5sum "{}" | cut -f1 -d " " | tr "\n" " "; du -h "{}"' | sort -h -k2 -r | uniq -w32 --all-repeated=separate

Этот пример:

  1. Находит все файлы в текущей директории и поддиректориях.
  2. Вычисляет MD5-хэш для каждого файла.
  3. Получает размер файла с помощью du -h.
  4. Сортирует результаты по размеру.
  5. Определяет дубликаты по MD5-хешам.

Хотя этот метод работает, он не является самым эффективным из-за использования xargs и односвязного подхода к вызову md5sum. Каждый файл обрабатывается отдельно, что увеличивает время выполнения.

Оптимизированный подход

Для улучшения производительности мы можем сгруппировать файлы и передать их в md5sum одним командным вызовом:

find . -type f -print0 | xargs -0 md5sum | sort | uniq -w32 --all-repeated=separate

Этот подход позволяет передавать несколько файлов одновременно в md5sum, что значительно уменьшает время выполнения. Однако вы не получаете информацию о размере файлов непосредственно с этим методом.

Включение размера файлов

Если вам необходимо также получить размер файлов, вы можете создать небольшую оболочку (shell-скрипт) для объединения информации о хешах и размерах:

find . -type f -print0 | xargs -0 md5sum | while read hash file; do
    size=$(du -h "$file" | cut -f1)  # Получаем размер файла в удобочитаемом формате
    echo "$hash $size $file"
done | sort -k2 -hr | uniq -w32 --all-repeated=separate

Этот скрипт:

  1. Использует find и xargs для получения MD5-хешей.
  2. Для каждого файла в цикле while просматривается его размер.
  3. Результаты сортируются по размеру и выводятся с соответствующими хешами.

Альтернативные инструменты

Если ваш рабочий характер ограничен стандартными утилитами или вы хотите более удобное решение, рассмотрите возможность использования fdupes, которое автоматически находит дубликаты файлов:

fdupes -r . | while read name; do
    size=$(stat -c %s "$name" 2>/dev/null)
    echo "$size  $name"
done | sort -n

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

Вывод

Подход с использованием команды find и xargs является наиболее оптимизированным. Однако для получения информации о размере вам подойдет использование цикла для извлечения необходимых данных. Если вы работаете в среде с ограничениями, можно использовать более простые скрипты, которые совместят необходимые операции. Бесспорно, выбор подхода зависит от условий вашей работы, поэтому важно выбирать наиболее подходящие методы, основываясь на потребностях проекта и доступных инструментах.

Оцените материал
Добавить комментарий

Капча загружается...