Преобразование идентичных файлов в hardlinks

У меня много музыки в дереве под одним каталогом, сохранено в любом формате, в котором я первоначально его получил, для качества. У меня есть второе дерево каталогов, похожее по структуре, но со всеми файлами в формате с потерями сжатия, воспроизводимым на моем телефоне, и со случайными изменениями метаданных (например, удаление встроенных обложек для экономии места).

Мне кажется, что для значительной части музыки нет разницы между двумя экземплярами – обычно, когда распределенная версия доступна только в формате mp3 / ogg и не имеет встроенных обложек. Пространство на жестком диске может быть дешевым, но это не повод тратить его. Есть ли способ сценария:

  1. Проверить идентичные файлы в двух каталогах
  2. Когда найдены одинаковые файлы, замените их на жесткую ссылку на другую
  3. Без, например, времени, чтобы получить полный разброс, в интересах времени
  4. Но все же без риска случайного удаления копии двух неидентичных файлов, что является удаленным, но отличным от нуля шансом, если я хотел бы, например, сравнить хэши?

  • Как заменить символическую ссылку на эквивалентную жесткую ссылку?
  • Содержит ли жесткие ссылки обычные файлы?
  • Есть ли лучший способ, чем cp, копировать миллионы файлов при сохранении жестких ссылок?
  • Совместное использование дерева проектов между средами
  • Linux: Как работает жесткая привязка к каталогу?
  • Параметр -link-dest от rsync не связан из-за времени файла
  • Есть ли разница между жесткой привязкой к cp -l или ln?
  • Количество ссылок для папки не отражает реальный статус?
  • 2 Solutions collect form web for “Преобразование идентичных файлов в hardlinks”

    Следующее использует md5 для создания дайджеста MD5 для всех файлов в текущем каталоге или ниже:

     find . -type f -exec md5 {} + 

    Замените md5 на md5sum --tag если у вас нет утилиты BSD md5 .

    Давайте создадим простой скрипт для этого в каталогах:

     #!/bin/bash tmpdir=${TMPDIR:-/tmp} if (( $# != 2 )); then echo 'Expected two directories as arguments' >&2 exit 1 fi i=0 for dir in "$@"; do (( ++i )) find "$dir" -type f -exec md5 {} + | sort -t '=' -k2 -o "$tmpdir/md5.$i" done 

    Это занимает две директории в командной строке и создает файлы с именем md5.1 и md5.2 , по одному файлу для каждой директории в /tmp (или везде, где указывается $TMPDIR ). Эти файлы сортируются по дайджесту MD5.

    Файлы будут выглядеть так:

     MD5 (<path>) = <MD5 digest> 

    с одной такой строкой для каждого файла.

    Затем в том же скрипте сравните контрольную сумму между двумя файлами:

     join -t '=' -1 2 -2 2 "$tmpdir"/md5.[12] 

    Это делает реляционную операцию «соединения» между двумя файлами, используя контрольную сумму в качестве поля объединения. Любые строки, которые имеют одну и ту же контрольную сумму в двух полях, будут объединены и выведены.

    Если в обоих файлах контрольная сумма одинакова, это будет выводить:

     <space><MD5 digest>=MD5 (<path1>) =MD5 (<path2>) 

    Это может быть передано awk непосредственно для разбора двух путей:

     awk -F '[()]' 'BEGIN { OFS="\t" } { print $2, $4 }' 

    -F [()] – это просто способ сказать, что мы хотели бы разделить каждую строку на поля, основанные на ( и ) . Это приводит нас к путям в полях 2 и 4.

    Это приведет к выводу

     <path1><tab><path2> 

    Тогда это просто вопрос чтения этих пар разделенных табуляцией путей и выдача правильных команд для создания ссылок:

     while IFS=$'\t' read -r path1 path2; do echo ln -f "$path1" "$path2" done 

    В итоге:

     #!/bin/bash tmpdir=${TMPDIR:-/tmp} if (( $# != 2 )); then echo 'Expected two directories as arguments' >&2 exit 1 fi i=0 for dir in "$@"; do (( ++i )) find "$dir" -type f -exec md5 {} + | sort -t '=' -k2 -o "$tmpdir/md5.$i" done join -t '=' -1 2 -2 2 "$tmpdir"/md5.[12] | awk -F '\\)|\\(' 'BEGIN { OFS="\t" } { print $2, $4 }' | while IFS=$'\t' read -r path1 path2; do echo ln -f "$path1" "$path2" done rm -f "$tmpdir"/md5.[12] 

    echo в цикле while для безопасности. Запустите его один раз, чтобы узнать, что произойдет, и удалите его и запустите снова, если вы уверены, что он поступает правильно.

    Помните, что жесткие ссылки не могут охватывать разделы. Это означает, что обе директории должны жить в одном разделе. Файлы во втором каталоге будут перезаписаны, если они будут найдены дублирующими. Храните резервную копию оригиналов где-нибудь, пока вы не будете довольны результатом!

    Обратите внимание, что это решение не будет работать должным образом, если какой-либо файл имеет ( или ) или вкладку в именах файлов.

    Если у вас нет большой коллекции очень похожих файлов, вычисление и сравнение хэшей не ускоряют процесс поиска дубликатов. Самая медленная операция – чтение диска. Вычисление хеша означает чтение всего файла, а также его интенсивную задачу с использованием криптографически сильных хешей.

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

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

    Interesting Posts

    Строка формата изображения IANA из двоичного потока

    Построение дебианской установки для платы Allwinner. Зачем нужен «последовательный» кабель?

    Что такое XRuns?

    Каков наиболее эффективный способ перемещения большого количества файлов, которые находятся в одном каталоге?

    Сколько пакетов предлагает RHEL 6?

    Пропустить logrotate для остановленных / отключенных приложений

    Условно разбить столбцы на 2 строки?

    Как центрировать окно в xfce?

    Как я могу получить шрифт Terminus на gnome-terminator?

    Как исправить полноэкранный режим вспышки, появляющийся сбоку экрана

    Реализация расширенного регулярного выражения для добавления переменной числа ведущих нулей на основе позиции в строке

    Как им удалось управлять компьютером Unix до мышей и скопировать и вставить?

    Есть ли дистрибутив Linux, который не установлен, но работает из браузера?

    неверная ошибка даты для% m% d% Y

    Могу ли я заставить bash игнорировать ведущий `:`, когда он присутствует?

    Linux и Unix - лучшая ОС в мире.