Готовая программа

#!/usr/bin/perl

use warnings;

my %collectedFiles;

sub compareFiles($$;$)
{
	my $name1=shift;
	my $name2=shift;
	my $bufferSize=shift // 512;
	unless(open $file1, '<', $name1)
	{
		warn "$0: Невозможно открыть «$name1»: $!\n";
		return;
	}
	unless(open $file2, '<', $name2)
	{
		warn "$0: Невозможно открыть «$name2»: $!\n";
		close $file1 or warn "$0: Невозможно закрыть «$name1»: $!";
		return;
	}
	my($buffer1, $buffer2);
	my $result=0;
	while()
	{
		my $n1=read $file1, $buffer1, $bufferSize;
		unless(defined $n1)
		{
			warn "$0: Невозможно прочитать «$name1»: $!\n";
			undef $result;
			last;
		}
		my $n2=read $file2, $buffer2, $bufferSize;
		unless(defined $n2)
		{
			warn "$0: Невозможно прочитать «$name2»: $!\n";
			undef $result;
			last;
		}
		last unless $n1 or $n2;
		if($buffer1 ne $buffer2)
		{
			$result=1;
			last;
		}
	}
	close $file2 or warn "$0: Невозможно закрыть «$name2»: $!";
	close $file1 or warn "$0: Невозможно закрыть «$name1»: $!";
	return $result;
}

sub find($);
sub find($)
{
	my $name=shift;
	if(-d $name)
	{
		my $dir;
		unless(opendir $dir, $name)
		{
			warn "$0: Невозможно открыть «$name»: $!\n";
			return;
		}
		$name='' if $name eq '/';
		for(readdir $dir)
		{
			next if $_ eq '.' or $_ eq '..';
			find("$name/$_");
		}
		closedir $dir;
	}
	elsif(-f $name)
	{
		push @{$collectedFiles{-s $name}->[0]}, $name;
	}
	else
	{
		warn "$0: «$name»: $!\n";
	}
}

sub findDups(@)
{
	push @_, '.' unless @_;
	find($_) for @_;
	for my $size(sort { $a<=>$b } keys %collectedFiles)
	{
		my $groups=$collectedFiles{$size};
		for(my $g=0; $g<@$groups; $g++)
		{
			my $group=$groups->[$g];
			for(my $i=1; $i<@$group; $i++)
			{
				push @{$groups->[$g+1]}, splice @$group, $i--, 1
					if compareFiles($group->[0], $group->[$i]);
			}
			if(@$group>1)
			{
				print "* Размер: $size\n";
				print "$_\n" for sort @$group;
				print "\n";
			}
		}
	}
}

findDups(@ARGV);
Информатика-54© А. Н. Швец