|
|||||||||||||||||||||||||||
On Tue, 8 Aug 2000, Peter Lindstrøm wrote:
> Hvis du finder en løsning på probelmet må du meget gerne poste den til
> gruppen da jeg har stort set samme problem.
> > Men det koster meget diskplads. Jeg vil hellere blot kopiere ændringer.
> > Det kunne jeg gøre ved:
> >
> > cp -a backup backup-`date '+%Y%m%d'`
> > find filer fælles med igår
> > hard-link filerne
Dette er løst nedenfor. Det er lidt langsomt:
2 x 250000 filer på ialt 2 x 3 GB tager 20 min og 10 CPU-minutter på min
Athlon.
Det kan sikkert laves hurtigere. Der bliver lavet en allerh..... masse
stat'er, så jeg overvejede at benytte filehandlet _ så jeg kunne spare et
par stat'er. Men det ville gøre koden mere ulæselig og sværere at
vedligeholde (Og som det er nu, giver det endnu en grund til at opgradere
til ReiserFS - den stat'er omtrendt dobbelt så hurtigt som ext2).
> > Men hvis en af filerne er en voksende logfil, så vil der spildes en del
> > plads, da starten af filen jo er fælles.
Dette er ikke løst.
Under testen fandt jeg ud af, at en "logfil" i øvrigt også kan være en
mail-folder, der ikke bliver læst.
/Ole
#!/usr/bin/perl
# Usage:
# link-same old new
#
# Description:
# Hardlinks files in dir1 to files in dir2 if content is the same
$debug=0;
use Digest::MD5;
$dstdir=shift;
$srcdir=shift;
examine_dir($srcdir,$dstdir);
sub examine_dir {
my $srcdir = shift; # start of source dirtree
my $dstdir = shift; # start of dest dirtree
my $subdir = shift || "."; # . if current dir
# Skip symbolic link to avoid endless recursion
-l $srcdir and return;
-d "$srcdir/$subdir" || die("$srcdir/$subdir is not a dir");
opendir(DIR,"$srcdir/$subdir") || die;
# for each file in dir (except . and ..)
for $file (grep { not /^\.\.?$/ } readdir DIR) {
my $srcfile="$srcdir/$subdir/$file";
print $srcfile,"\n" if $debug;
# Skip symbolic link to avoid endless recursion
-l $srcfile and next;
if(-d $srcfile) {
# if directory: Recurse through that
examine_dir($srcdir,$dstdir,"$subdir/$file");
next;
} elsif (-f $srcfile) {
# if regular file: check MD5
my $dstfile="$dstdir/$subdir/$file";
# Skip symbolic link to avoid hardlinking to a symlink
-l $dstfile and next;
-f $dstfile and do {
if(same_md5($srcfile,$dstfile)) {
# Hardlink
unlink $dstfile || die;
link ($srcfile,$dstfile);
}
};
next;
};
}
}
sub same_md5 {
my $srcfile = shift;
my $dstfile = shift;
my $srcmd5 = Digest::MD5->new;
my $dstmd5 = Digest::MD5->new;
open(SRCFILE,$srcfile) || die;
open(DSTFILE,$dstfile) || die;
$srcmd5->addfile(*SRCFILE);
$dstmd5->addfile(*DSTFILE);
close SRCFILE;
close DSTFILE;
return($srcmd5->digest eq $dstmd5->digest);
}
|
||||||||||||||
|
||||||||||||||