我试图编写一个程序,递归地将所有文件从某个顶点读取到数组中,然后从一个单独的文件中读取文件名行,如果前面的数组中存在这些文件名,则尝试打印这些文件名。
我的程序遍历目录结构中的43K文件,然后遍历文件中400行中的大约300行,然后提供一个壮观的"* glibc检测到的 perl:损坏的双链接列表: 0x0000000000a30740 **“。
我一点也不知道..。这会是“内存不足”类型的错误吗?我无法想象这不是因为主机有24G的内存。
你知道我哪里出问题了吗?我试图节省时间和精力,方法是将整个文件列表从子目录中读取一次到数组中,然后使用文件名为ARGV的较短的文件列表进行匹配。
这是我的代码:
#!/usr/bin/perl
use warnings;
use strict;
use diagnostics;
use File::Find;
use 5.010001;
## debug subroutine
my $is_debug = $ENV{DEBUG} // 0;
sub debug { print "DEBUG: $_[0]\n" if $is_debug };
## exit unless properly called with ARGV
die "Please provide a valid filename: $!" unless $ARGV[0] && (-e $ARGV[0]);
my @pic_files;
my $pic_directory="/files/multimedia/pictures";
find( sub {
push @pic_files, $File::Find::name
if -f && ! -d ;
}, $pic_directory);
open LIST, '<', $ARGV[0] or die "Could not open $ARGV[0]: $!";
while(<LIST>) {
chomp;
debug "\$_ is ->$_<-";
if ( @pic_files ~~ /.*$_/i ) {
print "found: $_\n";
} else {
print "missing: $_\n";
}
}
close LIST or die "Could not close $ARGV[0]: $!";下面是该文件的示例:
DSC02338.JPG
DSC02339.JPG
DSC02340.JPG
DSC02341.JPG
DSC02342.JPG
DSC02343.JPG
DSC02344.JPG
DSC02345.JPG
DSC02346.JPG
DSC02347.JPG 以及义务错误:
missing: DSC02654.JPG
DEBUG: is ->DSC02655.JPG<-
missing: DSC02655.JPG
DEBUG: is ->DSC02656.JPG<-
missing: DSC02656.JPG
*** glibc detected *** perl: corrupted double-linked list: 0x0000000000a30740 ***
======= Backtrace: =========
/lib/libc.so.6(+0x71bd6)[0x7fb6d15dbbd6]
/lib/libc.so.6(+0x7553f)[0x7fb6d15df53f] 提前感谢!
发布于 2012-08-21 08:53:48
这是一个非常低效的算法。您正在运行21,500 *n个regexes,其中n是列表中的文件数。我的猜测是,这会让你陷入某种潜在的内存问题或错误。
这里有一种替代方法,如果不进行许多更改,效率就会高得多。首先,将文件读入散列,而不是数组(我添加了lc以使所有内容都小写,因为您想要大小写不敏感的匹配):
my %pic_files;
find( sub {
$pic_files{lc $File::Find::name}++
if -f && ! -d ;
}, $pic_directory);编辑:第二,与其使用regex搜索目录中的每个文件,不如在输入行上使用regex智能地查找潜在的匹配项。
my $path_portion = lc $_;
my $found = 0;
do {
if (exists $pic_files{$path_portion} or exists $pic_files{'/' . $path_portion} )
{
$found = 1;
}
} while (!found and $path_portion =~ /\/(.*)$/ and $path_portion = $1);
if ($found) { print "found: $_"; }
else { print "not found: $_\n"; }这将检查输入文件中的路径,然后每次路径中的第一个目录与其不匹配时删除路径中的第一个目录,然后再次检查。它应该会快得多,并且希望这个奇怪的bug能够消失(尽管很高兴知道发生了什么;如果它是Perl中的一个bug,那么您的版本就变得非常重要,因为智能匹配是一个新特性,它最近进行了大量的更改和错误修复)。
发布于 2012-08-21 11:33:53
虽然我以前没有见过这样的错误,但我怀疑它是由生成43,000个元素的文件列表并在智能匹配中使用而引起的。您正在使用64位perl吗?
当您只需要匹配基本文件名时,存储到每个文件的完整路径也会使事情变得更加困难。
这确实不是智能匹配的好处,我建议您在输入文件中创建文件名的散列,并在find遇到它们时逐个标记它们。
这个节目展示了这个想法。我手头没有perl安装程序,所以我无法测试它,但它看起来还可以
use strict;
use warnings;
use File::Find;
my $listfile = shift;
die "Please provide a valid filename" unless $listfile;
open my $list, '<', $listfile or die "Unable to open '$listfile': $!";
my %list;
while (<$list>) {
chomp;
$list{$_} = 0;
}
close $list;
my $pic_directory = '/files/multimedia/pictures';
find( sub {
if (-f and exists $list{$_}) {
print "found: $_\n";
$list{$_}++;
}
}, $pic_directory);
for my $file (keys %list) {
print "missing: $_\n" unless $list{$file};
}https://stackoverflow.com/questions/12048566
复制相似问题