0

一个目录共有 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 }
}

编辑:

eval 就 BDI 错误咆哮了几次:

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;
4

1 回答 1

2

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

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

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

正如 Ether 所说,如果您粘贴在代码中,我们希望提供的不仅仅是一般的调查想法。

更新

基于您的代码:

  1. 请指出 eval 是否向 STDERR 发出任何声音

  2. 更重要的是,任何 IO 操作都需要进行错误检查。例如

    copy($something,$other)
        || die "Copy $something to $other died with error: $!\n"; # or print
    # Same for making the directory
    
于 2010-06-15T16:16:20.740 回答