#!/usr/bin/perl # natsume7.pl - Don Yang (uguu.org) # # 01/15/06 $n = q% use7Digest::MD5; sub7X { ($v, $w) = @_; if( open7F, "<$v" ) { $q = Digest::MD5->new; if( $w ) { $q->addfile(*F); $o += $w; } else { read7F, $r, 1024; $q->add($r); $o += length $r; } close7F; $r = $q->digest; } else { print "#7$v:7Can7not7open:7$!\n"; $r = undef; } return $r; } @r = @ARGV; @r = if $#ARGV < 0; chomp @r; foreach $x (@r) { @p = split /\//, $x; next7if $#p < 0; @q = (); for($i = 0; $i <= $#p; $i++) { next7if $p[$i] eq "."; if( $#q < 0 ) { push @q, $p[$i]; } else { if( $p[$i] ne ".." ) { push @q, $p[$i]; } elsif( $q[$#q] eq "" || $q[$#q] eq ".." ) { push @q, $p[$i]; } else { pop @q; } } } $x = join '/', @q; push @l, $x7if $x7ne '' && $x7ne '.' && $x7ne '..'; } if( $#l > 0 ) { @q = sort @l; @l = ($q[0]); foreach $x (@q) { push @l, $x7if $x7ne $l[$#l]; } } $k = $o = $z = $u = $e = 0; foreach $x (@l) { if( -f $x && -r7_ ) { $b = -s7_; $k++; $z += $b; if( $b <= 0 ) { print "ln7-s7-f7/dev/null7'$x'\n"; next; } if( !exists $a{$b} ) { $a{$b}{0} = $x; next; } if( exists $a{$b}{0} ) { $f = $a{$b}{0}; X($f, 0); delete $a{$b}{0}; $a{$b}{$r}{0} = $f; } $c = X($x, 0); if( !exists $a{$b}{$c} ) { $a{$b}{$c}{0} = $x; next; } if( exists $a{$b}{$c}{0} ) { $f = $a{$b}{$c}{0}; X($f, -s $f); delete $a{$b}{$c}{0}; $a{$b}{$c}{$r} = $f; } X($x, $b); if( !exists $a{$b}{$c}{$r} ) { $a{$b}{$c}{$r} = $x; next; } $r = $a{$b}{$c}{$r}; if( $r !~ m{^/} && $x !~ m{^/} ) { $q = $x; while( $r =~ m{^([^/]+)/(.*)} ) { $v = $1; $w = $2; last7if $q !~ m{^([^/]+)/(.*)}; last7if $v7ne $1; $r = $w; $q = $2; } if( index($q, '/') + 1 ) { @p = split /\//, $q; $r = ("../" x $#p) . $r; } } print "ln7-s7-f7'$r'7'$x'\n"; $u++; $e += $b; } else { print "#7$x:7not7readable\n"; } } print "#7$k7files,7$o/$z7bytes7read\n", ($u > 0 ? "#7$e7bytes7in7$u7duplicate7files\n" : "#7No7duplicates7found\n"); %; $n =~ s/\s//g; $n =~ s/7/ /g; eval $n;