[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Поиск и удаление дублирующих файлов



05.11.2011 21:07, Yuriy Kaminskiy пишет:
Sergey Stremidlo wrote:
   05.11.2011 08:13, Нагашибай Жанибек пишет:
Какие программы есть на эту тему? Желательно, чтоб можно было
посмотреть список файлов-дубляжей и выборочно удалить любой из них.


Вот моё творение:
Помимо того, что велосипед (fdupes!), несколько замечаний ниже:

     #! /bin/bash

     #       Алгоритм работы скрипта:
     #       1. Составить список файлов
     #       2. Вычислить все md5 суммы файлов
     #       3. Отсортировать список по md5 суммам
     #       4. Пройтись по списку, сравнивая попарно md5 записанные в
     строках и
     #          если текущая совпала с предыдущей то вывести обе, но одну
     пометить file: а другую dup:
     #          А чтобы третья и последующая так же не выдавали метки
     file: то можно использовать имя файла в предыдущей строке
     #          как флаг, и обнулять его после первого вывода метки file:
     #
     #            впоследствии можно скормить файл grep "^dup" и затем rm
     #
     #       Создаем файл блокировки find_duplicate.process чтобы
     повторно не запустился поиск
     #       одновременно в этом файле находится фраза, описывающая какие
     действия выполняет скрипт.
     #       Вот примеры того что бывает в этом файле:
     #       'Построение списка файлов...'
     #       '23634 of 3974653'

     #
     # fixme: перенаправить stderr в файл
     # такая команда не помогает:
     # 2>$0.errlog
exec 2>$0.errlog

+
     if [ -e $0.process ]
             then
             echo "Already running..."
Я бы не помещал флаг в той же директории, что и скрипт. И сделал бы его per-user.

будет учтено
             exit
             fi

     if [ $# -ne 2 ]
             then
             echo "Use: $0<dir>  <out_file>"
             exit
exit 1
             fi

     FINDDIR="$1"
     TMPNAME=`tempfile`

     echo 'Построение списка файлов...'>  $0.process

             #       составим список только файлов (исключая директории)

     find $FINDDIR -type f>  $TMPNAME.list
1)        "$FINDDIR"
2) использовать $TMPNAME.list и иже с ним - небезопасно.

TMPLIST=`tempfile`
TMPLIST2=`tempfile`
MD5LIST=`tempfile`
MD5SORT=`tempfile`
DUPS=`tempfile`
trap "rm -f $TMPLIST $TMPLIST2 $MD5LIST $MD5SORT $DUPS; exit" 0 INT TERM QUIT
find ...>$TMPLIST

будет учтено
             # отфильтруем не нужные

     cat $TMPNAME.list | grep -v "/Trash/">  $TMPNAME.list2
1) useless use of cat: grep -v "/Trash/" $TMPLIST ...>  $TMPLIST2
2) можно было бы запихнуть это в условие сразу в find -
find "$FINDDIR" -name Trash -prune -o -type f -print

     mv $TMPNAME.list2 $TMPNAME.list

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

     CNT=`grep -c "" $TMPNAME.list`
s/grep -c ""/wc -l/

+
     # вычислим суммы файлов
     rm -f $TMPNAME.md5
     n=1
     while read FN
             do
             echo "$n of $CNT">  $0.process
             MD5=`md5sum "$FN"`
I'd prefer higher efficiency over UI frills.

tr '\n' '\0'<  $TMPLIST | xargs -0r md5sum>$MD5LIST

учту
             echo "$MD5">>  $TMPNAME.md5
             let n=n+1
             done<  $TMPNAME.list
     rm $0.process
     rm $TMPNAME.list

     MD5PRE=
     FNPRE=

     rm -f $TMPNAME.dup

     n=1
     sort $TMPNAME.md5>  $TMPNAME.md5.sorted
     rm -f $TMPNAME.md5
     while read LINE
             do
             MD5=${LINE%% *}
             FN=${LINE#*  }
while read MD5 FN
...
не окажется ли FN до первого пробела в имени файла?
             if [ "$MD5" = "$MD5PRE" ]
             then
                     #       если мд5 текущего и предыдущего совпали
                     #       но имя предыдущего файла не пустое, значит
     выводим две строки
                     #       и опустошаем имя предыдущего файла чтобы по
     этому признаку определить
                     #       что нужно выводить одну строку а не две
                     if [ "$FNPRE" != "" ]
                       if [ -n "$FNPRE" ]
                     then
... но я бы для поиска дупликатов заюзал uniq -w32 -D :-)

понял, понравилось, но тут более далекая задумка, а именно: fille и dup - впоследствии заменить командами,
например dup внутри выполняет rm -f $1
Но это примитивно, а задумал я впоследствии такой проект:
собирать базу файлов на всех компах где я работаю и иметь что-то вроде распределенного хранилища этой базы, как git или mercurial. Т.е. отсканировал дома файлы и кинул на работу список, затем отсканировал на работе и импортировал домашний список. В итоге я запускаю свой поиск и вижу что на работе у меня есть те же файлы что и дома или каких-то не хватает. В свою очередь я домой отправляю список рабочих файлов и могу увидеть каких у меня не хватает дома. Аналогичные операции я проделываю на бекап-машине и докидываю туда то что хотел бы сохранить при крахе. Но и это еще не все. Имея такую базу можно не только производить поиск не имея доступа к удаленной машине, но и вести классификатор файлов. Т.е. имея md5 суммы книг можно им приписать теги и вести библиотеку. Поискать нужные книги по темам и увидеть на каком компе они валяются. Вот такая вот глобальная задумка. А реализовать это надо текстовыми файлами чтобы было просто обрабатывать списки, без всяких там СУБД,
написать красивый гуй на Lazarus и наслаждаться коллекционированием.
                             echo "file: $FNPRE">>  $TMPNAME.dup
                             echo " dup: $FN">>  $TMPNAME.dup
                             FNPRE=
                     else
                             echo " dup: $FN">>  $TMPNAME.dup
                     fi
                     let n=n+1
             else
                     MD5PRE=$MD5
                     FNPRE=$FN
             fi
             done<  $TMPNAME.md5.sorted
     rm -f $TMPNAME.md5.sorted
     mv $TMPNAME.dup "$2"
Ах да, коллизии для md5 не новость, давно пора переходить с md5 на более другой
хеш; учитывая, что sha1 уже тоже дисквалифицирован, можно сразу на sha256 (или
sha512).




Reply to: