为什么File :: Find完全没有完全遍历大目录?

时间:2010-06-15 15:49:48

标签: perl ntfs file-find

存在一个共有2,153,425个项目的目录(根据Windows文件夹属性)。它包含位于几个子目录中的.jpg和.gif图像文件。任务是将图像移动到不同的位置,同时查询每个文件的名称以检索一些相关信息并将其存储在其他位置。

使用File :: Find的脚本在20462文件中完成。出于好奇,我写了一个小的递归函数来计算返回计数为1,734,802的项目。我想差异可以归结为它不计算文件夹,只计算通过-f测试的文件。

通过首先查询文件名而不是遍历目录,可以以不同方式解决问题本身。我只是想知道什么可能导致File :: Find完成所有文件的一小部分。

数据存储在NTFS文件系统中。

以下是剧本的内容;我不认为包括DBI的东西是相关的,因为我重新编写脚本,除了process_img()中的一个计数器,它返回相同的数字。

find(\&process_img, $path_from);

sub process_img {
    eval {
        return if ($_ eq "." or $_ eq "..");

        ## Omitted querying and composing new paths for brevity.

        make_path("$path_to\\img\\$dir_area\\$dir_address\\$type");
        copy($File::Find::name, "$path_to\\img\\$dir_area\\$dir_address\\$type\\$new_name");
    };
    if ($@) { print STDERR "eval barks: $@\n"; return }
}

编辑:

对于BDI错误,eval咆哮了几次:

DBD::CSV::db do failed: Mismatched single quote before:
'INSERT INTO img_info (path, type, floorplan, legacy_id)
        VALUES (
            ?0?building?1?0?2?19867'
        )' at C:/perl/site/lib/SQL/Statement.pm line 77
[for Statement "
INSERT INTO img_info (path, type, floorplan, legacy_id)
        VALUES (
            'wal/15 Broad Street/building/nyc-Wall-St--South-St--Seaport-condo-elevator- building-52201501.jpg',
            'building',
            '0',
            '19867'
        )
"]

我认为这是由于'St'和'South'之间的双击。没有报告其他性质的错误。

这是我用来计算文件的另一种方法:

count_images($path_from);
sub count_images {
    my $path = shift;

    opendir my $images, $path or die "died opening $path";
    while (my $item = readdir $images) {
        next if $item eq '.' or $item eq '..';
        $img_counter++ && next if -f "$path/$item";
        count_images("$path/$item") if -d "$path/$item";
    }
    closedir $images or die "died closing $path";
}

print $img_counter;

1 个答案:

答案 0 :(得分:2)

它可能耗尽了资源? (内存,文件描述符等......?)。

或者它可能是一些时髦的文件名(很容易通过重新运行测试,但删除10个文件 - 如果它停在完全相同的文件,该文件名是罪魁祸首)

如果你可以跟踪内存占用,那就告诉你是否有内存泄漏(请参阅最近有关内存泄漏的SO问题以帮助解决)。

正如以太所说的,如果你粘贴在代码中,我们可以提供比一般调查想法更多的希望。

<强>更新

基于您的代码:

  1. 请说明eval是否对STDERR

  2. 咆哮
  3. 更重要的是,任何IO操作都需要进行错误检查。 E.g。

    copy($something,$other)
        || die "Copy $something to $other died with error: $!\n"; # or print
    # Same for making the directory