Вы имеете в виду фактическое генетическое программирование, в противоположность генетическим алгоритмам в целом?
Если так, C#/.net не является лучшим языком для него. LISP, например, всегда был оплотом GP.
Однако, если Вы должны, Вы, вероятно, собираетесь хотеть динамично генерировать CIL / MSIL. Вы могли сделать это использование Система. Отражение. Испустите , однако я рекомендовал бы Моно. Cecil. Это испытывает недостаток в хороших документах (как будто отражение испускает, имеет их).. Но это предлагает намного лучшую эмиссию блока и отражение.
Другая проблема - то, что это менее, чем тривиально, чтобы загрузить код, и позже избавиться от него, в .net платформе. По крайней мере, Вы не можете разгрузить блоки. Можно разгрузить appdomains, но целый бизнес загружающегося кода в отдельный appdomain и вызов его внешне могут стать довольно грязными..NET 3.5's Система. Дополнительный материал должен сделать это легче.
Perl с модулем Digest :: MD5.
use Digest::MD5 ;
%seen = ();
while( <*> ){
-d and next;
$filename="$_";
print "doing .. $filename\n";
$md5 = getmd5($filename) ."\n";
if ( ! defined( $seen{$md5} ) ){
$seen{$md5}="$filename";
}else{
print "Duplicate: $filename and $seen{$md5}\n";
}
}
sub getmd5 {
my $file = "$_";
open(FH,"<",$file) or die "Cannot open file: $!\n";
binmode(FH);
my $md5 = Digest::MD5->new;
$md5->addfile(FH);
close(FH);
return $md5->hexdigest;
}
Если Perl не является обязательным и вы работаете над * nix, вы можете использовать инструменты оболочки
find /path -type f -print0 | xargs -0 md5sum | \
awk '($1 in seen){ print "duplicate: "$2" and "seen[$1] } \
( ! ($1 in seen ) ) { seen[$1]=$2 }'
md5sum *.txt | perl -ne '
chomp;
($sum, $file) = split(" ");
push @{$files{$sum}}, $file;
END {
foreach (keys %files) {
shift @{$files{$_}};
unlink @{$files{$_}} if @{$files{$_}};
}
}
'
Варианты на тему:
md5sum *.txt | perl -lne '
my ($sum, $file) = split " ", $_, 2;
unlink $file if $seen{$sum} ++;
'
Не нужно идти и вести список, просто удалите один из списка и удалите остальные; просто следите за тем, что вы видели раньше, и удалите все файлы, соответствующие сумме, которая уже была просмотрена. Разделение на 2 предела - это правильная вещь с именами файлов, содержащими пробелы.
Кроме того, если вы не доверяете этому, просто замените слово unlink
на print
и оно выведет список файлов, которые нужно удалить. Вы даже можете записать этот вывод в файл, а затем rm $ (cat to-delete.txt)
в конце, если он выглядит хорошо.
сценарий bash более выразителен, чем perl в этом случае:
md5sum * |sort -k1|uniq -w32 -d|cut -f2 -d' '|xargs rm
Я бы порекомендовал вам сделать это на Perl и использовать File :: Find , пока вы на нем.
Кто знает, что вы делаете для создания списка файлов, но вы можете объединить это с проверкой дубликатов.
perl -MFile::Find -MDigest::MD5 -e '
my %m;
find(sub{
if(-f&&-r){
open(F,"<",$File::Find::name);
binmode F;
$d=Digest::MD5->new->addfile(F);
if(exists($m{$d->hexdigest}){
$m{$d->hexdigest}[5]++;
push $m{$d->hexdigest}[0], $File::Find::name;
}else{
$m{$d->hexdigest} = [[$File::Find::name],0,0,0,0,1];
}
close F
}},".");
foreach $d (keys %m) {
if ($m{$d}[5] > 1) {
print "Probable duplicates: ".join(" , ",$m{$d}[0])."\n\n";
}
}'
Вот способ фильтрации сначала по размеру, а затем по md5
контрольной сумме:
#!/usr/bin/perl
use strict; use warnings;
use Digest::MD5 qw( md5_hex );
use File::Slurp;
use File::Spec::Functions qw( catfile rel2abs );
use Getopt::Std;
my %opts;
getopt('de', \%opts);
$opts{d} = '.' unless defined $opts{d};
$opts{d} = rel2abs $opts{d};
warn sprintf "Checking %s\n", $opts{d};
my $files = get_same_size_files( \%opts );
$files = get_same_md5_files( $files );
for my $size ( keys %$files ) {
for my $digest ( keys %{ $files->{$size}} ) {
print "$digest ($size)\n";
print "$_\n" for @{ $files->{$size}->{$digest} };
print "\n";
}
}
sub get_same_md5_files {
my ($files) = @_;
my %out;
for my $size ( keys %$files ) {
my %md5;
for my $file ( @{ $files->{$size}} ) {
my $contents = read_file $file, {binmode => ':raw'};
push @{ $md5{ md5_hex($contents) } }, $file;
}
for my $k ( keys %md5 ) {
delete $md5{$k} unless @{ $md5{$k} } > 1;
}
$out{$size} = \%md5 if keys %md5;
}
return \%out;
}
sub get_same_size_files {
my ($opts) = @_;
my $checker = defined($opts->{e})
? sub { scalar ($_[0] =~ /\.$opts->{e}\z/) }
: sub { 1 };
my %sizes;
my @files = grep { $checker->($_) } read_dir $opts->{d};
for my $file ( @files ) {
my $path = catfile $opts->{d}, $file;
next unless -f $path;
my $size = (stat $path)[7];
push @{ $sizes{$size} }, $path;
}
for my $k (keys %sizes) {
delete $sizes{$k} unless @{ $sizes{$k} } > 1;
}
return \%sizes;
}
Вы можете посмотреть, как я находил повторяющиеся файлы и удалял их. Хотя вам придется изменить его в соответствии с вашими потребностями.
Perl - своего рода излишество для этого:
md5sum * | sort | uniq -w 32 -D | cut -b 35- | tr '\n' '\0' | xargs -0 rm
(Если вам не хватает некоторых из этих утилит или у них нет этих флагов / функций, установите GNU findutils и coreutils.)
Here's a general algorithm (edited for efficiency now that I've shaken off the sleepies -- and I also fixed a bug that no one reported)... :)
It's going to take forever (not to mention a lot of memory) if I compare every single file's contents against every other. Instead, why don't we apply the same search to their sizes first, and then compare checksums for those files of identical size.
So then when we md5sum every file (see Digest::MD5) calculate their sizes, we can use a hash table to do our matching for us, storing the matches together in arrayrefs:
use strict;
use warnings;
use Digest::MD5 qw(md5_hex);
my %files_by_size;
foreach my $file (@ARGV)
{
push @{$files_by_size{-s $file}}, $file; # store filename in the bucket for this file size (in bytes)
}
Now we just have to pull out the potential duplicates and check if they are the same (by creating a checksum for each, using Digest::MD5), using the same hashing technique:
while (my ($size, $files) = each %files_by_size)
{
next if @$files == 1;
my %files_by_md5;
foreach my $file (@$files_by_md5)
{
open my $filehandle, '<', $file or die "Can't open $file: $!";
# enable slurp mode
local $/;
my $data = <$filehandle>;
close $filehandle;
my $md5 = md5_hex($data);
push @{$files_by_md5{$md5}}, $file; # store filename in the bucket for this MD5
}
while (my ($md5, $files) = each %files_by_md5)
{
next if @$files == 1;
print "These files are equal: " . join(", ", @$files) . "\n";
}
}
-fini