Я хочу удалить дубликаты файлов на основе их значения MD5. Я уже получил сценарий ниже, но как мне изменить его, чтобы он работал рекурсивно?

Так, например, у меня есть папка, содержащая 3 подпапки A B C

Я хочу, чтобы все эти файлы были в././A/./B/./C/ проверил их md5 и сравнил друг с другом, если положительное совпадение найдено, просто случайным образом удалите любое совпадение. В конце концов, больше нет дубликатов. Мне все равно, какой матч удаляется первым.

Я надеюсь, что я выразил то, что мне нужно, чтобы достичь достаточно ясно, если нет, пожалуйста, дайте мне знать :)

#!/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

2 ответа2

1

Во-первых, предостережение: предполагать идентичность на основе контрольной суммы очень опасно. Не рекомендуется.

Использование контрольной суммы в качестве фильтра для удаления определенных недубликатов - это нормально.

Если бы я делал это, я бы подошел к этому так:

  1. Создать список файлов на основе длины (длина, полное имя пути)

  2. Отсканируйте этот список в поисках возможных повторяющихся длин.

  3. Любые совпадения являются потенциальными дубликатами, и я бы сравнил подозрительные файлы должным образом, если это возможно.

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

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

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

0

Я бы порекомендовал что-то вроде следующего:

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

При этом будут перечислены все дублированные файлы в группах файлов с одинаковым хешем MD5.

Будьте внимательны , поскольку аргумент -w32 для uniq будет сравнивать только первые 32 символа ... если вы измените длину хеша, вам нужно будет обновить это.


Рассмотрим следующее дерево со следующим содержанием:

./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

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

Если вы не слишком обеспокоены тем, какой файл будет удален, то что-то вроде этого работает:

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

Обратите внимание, что MD5 больше не считается безопасным... поэтому, если вы используете это в системе, где пользователи имеют контроль над файлами, тогда для них вполне возможно спроектировать коллизию - и, таким образом, вы случайно удалите легитимного / целевого объекта файл вместо дедупликации, как вы надеялись. Предпочитаю более сильный хеш, такой как SHA-256.

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