Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

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

9 views
Skip to first unread message

Нагашибай Жанибек

unread,
Nov 5, 2011, 12:20:01 AM11/5/11
to
Какие программы есть на эту тему? Желательно, чтоб можно было
посмотреть список файлов-дубляжей и выборочно удалить любой из них.


--
To UNSUBSCRIBE, email to debian-russ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listm...@lists.debian.org
Archive: http://lists.debian.org/20111105101336.6bab8fed@DOM-131

Фролов Александр

unread,
Nov 5, 2011, 4:40:02 AM11/5/11
to
On 05.11.2011 08:13, Нагашибай Жанибек wrote:
> Какие программы есть на эту тему? Желательно, чтоб можно было
> посмотреть список файлов-дубляжей и выборочно удалить любой из них.
>
>
Гугли морды к fdupes или подобное.


--
To UNSUBSCRIBE, email to debian-russ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listm...@lists.debian.org
Archive: http://lists.debian.org/4EB4F4AF...@yandex.ru

Sergej Kochnev

unread,
Nov 5, 2011, 4:40:02 AM11/5/11
to
On Sat, 5 Nov 2011 10:13:36 +0600
Нагашибай Жанибек <njm....@yandex.ru> wrote:

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

fdupes

Sergey Stremidlo

unread,
Nov 5, 2011, 9:50:01 AM11/5/11
to
В Sat, 5 Nov 2011 10:13:36 +0600
Нагашибай Жанибек <njm....@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"


--
To UNSUBSCRIBE, email to debian-russ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listm...@lists.debian.org
Archive: http://lists.debian.org/20111105174522.5252d227@serega-pc

Sergey Stremidlo

unread,
Nov 5, 2011, 10:00:02 AM11/5/11
to
05.11.2011 08:13, Нагашибай Жанибек пишет:
Какие программы есть на эту тему? Желательно, чтоб можно было
посмотреть список файлов-дубляжей и выборочно удалить любой из них.


Вот моё творение:

#! /bin/bash

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

Yuriy Kaminskiy

unread,
Nov 5, 2011, 1:10:01 PM11/5/11
to
Sergey Stremidlo wrote:
> 05.11.2011 08:13, Нагашибай Жанибек пишет:
>> Какие программы есть на эту тему? Желательно, чтоб можно было
>> посмотреть список файлов-дубляжей и выборочно удалить любой из них.
>>
>>
> Вот моё творение:

Помимо того, что велосипед (fdupes!), несколько замечаний ниже:
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
...
> if [ "$MD5" = "$MD5PRE" ]
> then
> # если мд5 текущего и предыдущего совпали
> # но имя предыдущего файла не пустое, значит
> выводим две строки
> # и опустошаем имя предыдущего файла чтобы по
> этому признаку определить
> # что нужно выводить одну строку а не две
> if [ "$FNPRE" != "" ]
if [ -n "$FNPRE" ]
> then

... но я бы для поиска дупликатов заюзал uniq -w32 -D :-)

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


--
To UNSUBSCRIBE, email to debian-russ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listm...@lists.debian.org
Archive: http://lists.debian.org/j93qgu$49v$1...@dough.gmane.org

Artem Chuprina

unread,
Nov 5, 2011, 1:30:02 PM11/5/11
to
> > Какие программы есть на эту тему? Желательно, чтоб можно было
> > посмотреть список файлов-дубляжей и выборочно удалить любой из них.
> >
> >
>
> Моё творение:
>
> #! /bin/bash
>
> # Алгоритм работы скрипта:
> # 1. Составить список файлов
> # 2. Вычислить все md5 суммы файлов

Сходу: это надо делать только после того, как отфильтрованы файлы, чей размер
не совпадает ни с каким другим. Большие файлы обычно характерны тем, что
шансов на совпадение размера у них немного, а считать даже md5 от них можно
заманаться.
wc -l

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

--
Чушь для ресниц (С)энта


--
To UNSUBSCRIBE, email to debian-russ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listm...@lists.debian.org
Archive: http://lists.debian.org/87wrbeiix6.wl%r...@ran.pp.ru

Ivan Shmakov

unread,
Nov 5, 2011, 1:40:01 PM11/5/11
to
>>>>> Нагашибай Жанибек <njm....@yandex.ru> writes:

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

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

Эта операция, если выполняется правильно (в частности, что
очевидно, файлы не должны меняться в процессе проверки), не
допускает потери данных.

--
FSF associate member #7257

Иван Лох

unread,
Nov 5, 2011, 1:50:02 PM11/5/11
to
On Sun, Nov 06, 2011 at 12:35:06AM +0700, Ivan Shmakov wrote:
>
> Несколько не в тему. Вместо удаления повторов, я обычно заменяю
> их одним файлом с несколькими именами (e. g., через ln(1))
> предварительно проверив совпадение mtime и содержимого. (И,
> конечно, то, что это /различные/ файлы.)
>
> Эта операция, если выполняется правильно (в частности, что
> очевидно, файлы не должны меняться в процессе проверки), не
> допускает потери данных.

Да, но....


$ echo "1:1" >site1/passwd
$ echo "1:1" >site2/passwd
$ Поискали
$ rm site2/passwd && ln site1/passwd site2/passwd
$ ...
$ echo "2:2" >site2/passwd
$ cat site1/passwd

Оп! Этого ли Вы хотели?

--
Иван Лох


--
To UNSUBSCRIBE, email to debian-russ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listm...@lists.debian.org
Archive: http://lists.debian.org/2011110517...@nano.ioffe.rssi.ru

Ivan Shmakov

unread,
Nov 5, 2011, 2:20:01 PM11/5/11
to
>>>>> Иван Лох <l...@1917.com> writes:
>>>>> On Sun, Nov 06, 2011 at 12:35:06AM +0700, Ivan Shmakov wrote:

>> Несколько не в тему. Вместо удаления повторов, я обычно заменяю их
>> одним файлом с несколькими именами (e. g., через ln(1))
>> предварительно проверив совпадение mtime и содержимого. (И,
>> конечно, то, что это /различные/ файлы.)

>> Эта операция, если выполняется правильно (в частности, что очевидно,
>> файлы не должны меняться в процессе проверки), не допускает потери
>> данных.

> Да, но....

> $ echo "1:1" >site1/passwd
> $ echo "1:1" >site2/passwd
> $ Поискали
> $ rm site2/passwd && ln site1/passwd site2/passwd

rm(1) не требуется. ln(1) атомарно изменит второе имя файла
так, чтобы оно ссылалось на тот же файл, что и первое.

> $ ...
> $ echo "2:2" >site2/passwd
> $ cat site1/passwd

> Оп! Этого ли Вы хотели?

Во-первых, такого рода замену я выполняю только в тех
директориях, в которых файлы de facto являются read-only. Вроде
~/public/files/ (который у меня вместо ~/Downloads/.)

Во-вторых:

$ echo 2:2 > site2/passwd.tmp && mv -- site2/passwd.tmp site2/passwd

По крайней мере так поступают программы, вроде mv(1), rsync(1),
да и некоторые текстовые редакторы, полагаю, при соответствующей
настройке.

В противном случае несложно оказаться в ситуации, когда старое
содержимое уже удалено, а новое не удалось записать по причине,
e. g., отсутствия свободного пространства на ФС. Поэтому, такое
поведение программы для меня — повод написать отчет в BTS.

Sergey Stremidlo

unread,
Nov 5, 2011, 2:50:01 PM11/5/11
to
05.11.2011 21:07, Yuriy Kaminskiy пишет:
+
>> 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).
>
>


--
To UNSUBSCRIBE, email to debian-russ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listm...@lists.debian.org
Archive: http://lists.debian.org/4EB583F5...@gmail.com

Andrey Rahmatullin

unread,
Nov 6, 2011, 9:40:02 AM11/6/11
to
On Sun, Nov 06, 2011 at 12:35:06AM +0700, Ivan Shmakov wrote:
> >>>>> Нагашибай Жанибек <njm....@yandex.ru> writes:
>
> > Какие программы есть на эту тему? Желательно, чтоб можно было
> > посмотреть список файлов-дубляжей и выборочно удалить любой из них.
>
> Несколько не в тему. Вместо удаления повторов, я обычно заменяю
> их одним файлом с несколькими именами (e. g., через ln(1))
> предварительно проверив совпадение mtime и содержимого. (И,
> конечно, то, что это /различные/ файлы.)
apt-get install hardlink


--
WBR, wRAR
signature.asc

Michael Shigorin

unread,
Nov 19, 2011, 8:30:02 AM11/19/11
to
On Sun, Nov 06, 2011 at 08:31:09PM +0600, Andrey Rahmatullin wrote:
> > > Какие программы есть на эту тему? Желательно, чтоб можно
> > > было посмотреть список файлов-дубляжей и выборочно удалить
> > > любой из них.
> > Несколько не в тему. Вместо удаления повторов, я обычно
> > заменяю их одним файлом с несколькими именами (e. g.,
> > через ln(1)) предварительно проверив совпадение mtime и
> > содержимого. (И, конечно, то, что это /различные/ файлы.)
> apt-get install hardlink

JFYI, ldv@ некоторое время тому рекомендовал вместо него hardlinkpy.
В дебиане будто не наблюдаю -- http://hardlinkpy.googlecode.com/

--
---- WBR, Michael Shigorin <mi...@altlinux.ru>
------ Linux.Kiev http://www.linux.kiev.ua/


--
To UNSUBSCRIBE, email to debian-russ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listm...@lists.debian.org
Archive: http://lists.debian.org/20111119130...@osdn.org.ua

Serhiy Storchaka

unread,
Nov 19, 2011, 10:00:02 AM11/19/11
to
19.11.11 15:07, Michael Shigorin написав(ла):
> On Sun, Nov 06, 2011 at 08:31:09PM +0600, Andrey Rahmatullin wrote:
>>>> Какие программы есть на эту тему? Желательно, чтоб можно
>>>> было посмотреть список файлов-дубляжей и выборочно удалить
>>>> любой из них.
>>> Несколько не в тему. Вместо удаления повторов, я обычно
>>> заменяю их одним файлом с несколькими именами (e. g.,
>>> через ln(1)) предварительно проверив совпадение mtime и
>>> содержимого. (И, конечно, то, что это /различные/ файлы.)
>> apt-get install hardlink
>
> JFYI, ldv@ некоторое время тому рекомендовал вместо него hardlinkpy..
> В дебиане будто не наблюдаю -- http://hardlinkpy.googlecode.com/

Пользовался fdupes. Потом переписал на Python (дополнив и ускорив).
fdupes.py
0 new messages