Главная Облако тегов     Подписка на ленту обновлений (RSS) XMPP (Jabber) совместимые службы мгновенных сообщений. К примеру Google Talk, Gizmo, jabber.org Пишите письма О сайте
Вы находитесь здесь: Заметки экспериментатора » Projects » Поиск дубликатов
Translations of this page:

Поиск дубликатов

Это небольшое приложение написанное на Perl'е. Оно позволяет сравнить два каталога (рекурсивно), обнаружить и при необходимости удалить из второго каталога дубликаты файлов из первого. Сравнение проводится вычислением md5 сумм.

Написал я эту программу более года назад и считаю, что достаточно обкатал его. Работа проверялась под WinXP и Debian GNU/Linux.

Скачать

Инсталляция

Просто распакуйте в любое удобное для Вас место.

Если у вас юниксоподобная система и perl установлен (а он по умолчанию установлен практически везде), то запуск обычный

./finddupe

Если Вы несчастный обладатель windows придётся потрудится. Скачиваем дистрибутив и устанавливаем perl. Это может быть ActivePerl. Я сам не пробовал, поскольку под виндой у меня всегда перл ставился вместе с Apache.

Для конкретности переименуйте finddupe в finddupe.pl. И если в переменной path прописаны пути к перлу, то можно запустить из консоли:

perl finddupe.pl

Использование

Ключики которые программа понимает она сама Вам покажет будучи запущена без параметров или с параметром -h.

Небольшой пример использования:

finddupe -d -i first/ -o second/

Программа просмотрит каталоги first и second и удалит из second все файлы которые есть в first

Исходный код

Последняя версия v0.2.1

#!/usr/bin/perl -w
#
#    Finddupe v0.2.1 use for search and delete duplicate files
#    Copyright (C)  2005-2006 Ivan A. Alferov <ivan@iar.spb.ru>
#
#    web: http://iar.spb.ru/projects/finddupe
#
#	original name: finddupe
 
use Digest::MD5;
use Getopt::Std;
 
getopts('hlvspdi:o:', \%args);
 
if ($args{l})
{
	print <<EOF;
License:
 
Finddupe v0.2 use for search and delete duplicate files
Copyright (C) 2005-2006 Ivan A. Alferov <ivan\@iar.spb.ru>
                        http://iar.spb.ru
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
EOF
	exit;
}
 
 
if ($args{h} || !($args{i} && $args{o}))
{
    print <<EOF;
Finddupe v0.2.1 use for search and delete duplicate files
Copyright (C) 2005-2006 Ivan A. Alferov <ivan\@iar.spb.ru>
                        http://iar.spb.ru
 
Usage: finddupe [-h] [-i inpath -o outpath]
    -h -- this help
    -l -- license
    -v -- more verbose
    -s -- slience
    -d -- delete duplicates
    -p -- delete empty dir on destination directory
    -i inpath -- source directory path
    -o outpath -- destination directory path (hereof remove)
 
Platform supported: linux, WinXP, maybe platform independent.
 
EOF
    exit;
}
 
$srcpath = $args{i};
$dstpath = $args{o};
 
$regexp = 0;
 
%LIST1 = ();
 
print "Analizing $srcpath...\n";
lsr($srcpath, \%LIST1);
print "Compare $srcpath and $dstpath...\n";
rrem($dstpath, \%LIST1);
 
print "Done.\n";
 
 
### sub rrem ($directory, \%hash)
# Удаляет файлы совпадающие
sub rrem
{
    my $dir = shift;
    $dir .= '/' unless ($dir =~ m{[\\/]$});
    my $lst = shift;
    my $name;
    my $D;
    opendir $D, $dir;
    my $cnt = 0;
    while ($name = readdir $D)
    {
        if ($name !~ /^\./)
        {
            my $fullname = $dir.$name;
            unless (eval($regexp))
            {
                if (-d $fullname)
                {
                    $cnt += &rrem($fullname, $lst);
                }
                else
                {
                    my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat($fullname);
                    print "Check: $name: $size\n" if ($args{v});
                    if (($source = $$lst{"$name/$size"}) && ($$lst{"$name/$size"} ne $fullname))
                    {
                        my $ctx = Digest::MD5->new;
                        open (*FILE, $source);
                        $ctx->addfile(*FILE);
                        close (*FILE);
                        my $md5_1 = $ctx->hexdigest;
 
                        $ctx = Digest::MD5->new;
                        open (*FILE, $fullname);
                        $ctx->addfile(*FILE);
                        close (*FILE);
                        my $md5_2 = $ctx->hexdigest;
 
                        if ($md5_1 eq $md5_2)
                        {
                        	if( $args{d} )
                        	{
                            	unlink $fullname;
                            	print "Remove: $fullname\n" unless ($args{'s'});
							}
							else
							{
                            	print "Duplicate: $fullname\n" unless ($args{'s'});
							}
                        }
                        else
                        {
                            $cnt++;
                        }
                    }
                    else
                    {
                        $cnt++;
                    }
                }
            }
        }
    }
    closedir $D;
    if ((!$cnt) && ($args{p}))
    {
        if (rmdir $dir)
        {
            print "Remove directory: $dir\n" unless ($args{'s'});
        }
        else
        {
            print "Can't remove directory: $dir\n" unless ($args{'s'});
        }
    }
    return $cnt;
}
 
 
### sub lsr ($directory, \%hash)
# Возвращает рекурсивный список файлов начиная с директории
sub lsr
{
    my $dir = shift;
    $dir .= '/' unless ($dir =~ m{[\\/]$});
    my $lst = shift;
    my $D;
    my $name;
    opendir $D, $dir;
    while ($name = readdir $D)
    {
        if ($name !~ /^\./)
        {
            my $fullname = $dir.$name;
            unless (eval($regexp))
            {
                if (-d $fullname)
                {
                    &lsr($fullname, $lst);
                }
                else
                {
                    my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat($fullname);
                    print "Analize: $name: $size\n" if ($args{v});
                    $$lst{"$name/$size"} = $fullname;
                }
            }
        }
    }
    closedir $D;
}

Дискуссия

некто я, 2007/11/10 08:36

Мой пост на другом сайте: Очень нужно видеть папки-дубликаты, желательно в двух панелях (аля Norton Commander). Синхронное хождение по папкам - зашел в другую папку в текущей панели и автоматом в противоположной. Подсветка для почти одинаковых папок (несколько файлов разные/отсутствуют и т.д.). И еще не помешает фильтр на даты (изменения, создания), атрибуты и т.д., включая разные NTFS-примочки (потоки, коментарии и т.д.). Пожалуйста, посоветуйте, кто знает, где это есть (pk_income a*t mail.ru).


Пожелания к данному продукту на перле. Сравнение по md5 - только предварительное (результат - кандидаты на на полное, побайтное сравнение). И само полное сравнение.

Enter your comment (wiki syntax is allowed):
Краткая справка
  • **полужирный**
  • //курсив//
  • > цитата
  • [[http://link | Заголовок ссылки]]
Больше о синтаксисе...
За исключением случаев, когда указано иное, содержимое этой вики предоставляется на условиях следующей лицензии:CC Attribution-Noncommercial-Share Alike 3.0 Unported
projects/finddupe.txt · Последние изменения: 2006/10/31 21:45 (внешнее изменение)