Re: Поиск и удаление дублирующих файлов
В Sat, 5 Nov 2011 10:13:36 +0600
Нагашибай Жанибек <njm.janik@yandex.ru> пишет:
> Какие программы есть на эту тему? Желательно, чтоб можно было
> посмотреть список файлов-дубляжей и выборочно удалить любой из них.
>
>
Моё творение:
#! /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
if [ -e $0.process ]
then
echo "Already running..."
exit
fi
if [ $# -ne 2 ]
then
echo "Use: $0 <dir> <out_file>"
exit
fi
FINDDIR="$1"
TMPNAME=`tempfile`
echo 'Построение списка файлов...' > $0.process
# составим список только файлов (исключая директории)
find $FINDDIR -type f > $TMPNAME.list
# отфильтруем не нужные
cat $TMPNAME.list | grep -v "/Trash/" > $TMPNAME.list2
mv $TMPNAME.list2 $TMPNAME.list
# определим количество файлов
# для того чтобы отображать сколько файлов уже обработано
CNT=`grep -c "" $TMPNAME.list`
# вычислим суммы файлов
rm -f $TMPNAME.md5
n=1
while read FN
do
echo "$n of $CNT" > $0.process
MD5=`md5sum "$FN"`
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#* }
if [ "$MD5" = "$MD5PRE" ]
then
# если мд5 текущего и предыдущего совпали
# но имя предыдущего файла не пустое, значит выводим две строки
# и опустошаем имя предыдущего файла чтобы по этому признаку определить
# что нужно выводить одну строку а не две
if [ "$FNPRE" != "" ]
then
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"
Reply to: