Revision 3 (by ahitrov@rambler.ru, 2010/03/24 15:19:32) |
The CORE
|
#!/usr/bin/perl
use strict;
use warnings 'all';
use locale;
use Data::Dumper;
use FindBin;
use Getopt::Std;
my %opts;
getopts('hkn', \%opts);
&usage if $opts{h} || $#ARGV!=1 || ! -d $ARGV[0] || ! -f $ARGV[1];
$ARGV[0]=~s/\/+$/\//;
my $md5;
if ($opts{m}) {
$md5 = (`which md5`=~/(.*)/)[0] || (`which md5sum`=~/(.*)/)[0] || die "No md5 binary found\n";
$md5 .= ($md5=~/md5$/ ? ' -r ' : '');
}
my %snap;
open SNAP, "<$ARGV[1]" or die $!;
$_ = <SNAP>;
/^STATE=(MD5|MTIME)$/ or die "Unknown STATE line: $_\n";
my $stype = $1;
for (map {chomp; $_} <SNAP>) {
next unless /^(.+?)(\s+STATE=(.+))?$/;
if ($2) {
$snap{$1} = $3;
} else {
$snap{$1} = undef;
}
}
close SNAP;
for (grep {$snap{$_}} keys %snap) {
next unless -f "$ARGV[0]/$_";
my $state;
if ($stype eq 'MD5') {
$state = (`$md5 $ARGV[0]/$_ | awk '{print \$1}'`=~/(.*)/)[0];
} else {
$state = join(':', (stat("$ARGV[0]/$_"))[1,9]) or die $!;
}
if ($snap{$_} eq $state) {
unlink "$ARGV[0]/$_" unless $opts{n};
print " removing old file: $_\n";
} else {
print " skipping modified file: $_\n";
}
}
for (sort {(length($b)<=>length($a))||($a cmp $b)} grep {!$snap{$_}} keys %snap) {
opendir DIR, "$ARGV[0]/$_" or die $!;
my @cont = readdir DIR;
if ($#cont==1) {
rmdir "$ARGV[0]/$_";
print " removing empty dir: $_\n";
} else {
print " skipping non-empty dir: $_\n";
}
closedir DIR;
}
unlink $ARGV[1] unless $opts{k} || $opts{n};
sub usage {
print <<EOM;
Usage: $FindBin::RealScript [options] prefix file
Options:
-h Print this message
-k Keep file
-n Dry-run mode
EOM
exit;
}