You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

File::Find::Rule 输出重复问题排查求助

排查Perl子例程输出重复问题

问题描述

子例程可正确解析哈希并返回基本正确结果,但存在输出重复问题,实际输出内容重复了一遍。

示例数据

$local_h{$local}{name} = "somefile.txt";
$local_h{$local}{size} = 12345;

子例程代码

sub already_here {
    foreach my $local (keys(%local_h)) {
        my $tmp = $local_h{$local}{name};
        my $FFR_rule = File::Find::Rule
            ->size($local_h{$local}{size})
            ->start( @volumes );
        while ( defined ( my $match = $FFR_rule->match ) ) {
            my ( $name, $path, $suffix ) = fileparse($match);
            if ( $name =~ /$local_h{$local}{name}/ ) {
say "\t\$name $name has been matched by size and name to:\n\t $path$name\n";
#   Matches can occur multiple times, to be dealt with later/elsewhere
            } else {

say "$match  Matched by size only\n";
#   Maybe this really is the location but got renamed locally.
#   For now I will consider it an edge-case.
            }
        }
    }
}

实际输出

somefile.txt has been matched by size and name to: a/path/to/somefile.txt
somefile.txt has been matched by size and name to: some/other/path/to/somefile.txt 

34thx.foo   Matched by size only

somefile.txt has been matched by size and name to: a/path/to/somefile.txt
somefile.txt has been matched by size and name to: some/other/path/to/somefile.txt 

34thx.foo   Matched by size only

预期输出

仅看到3行有效输出(含空行共4行),无重复内容。


问题根源

输出重复的核心原因是**%local_h哈希中存在多个键**,导致foreach my $local (keys(%local_h))循环执行了多次。每次循环都会重新初始化File::Find::Rule并完整遍历@volumes目录,所以同一组匹配结果会被打印多遍。

你可以在循环前添加一行代码验证键的数量:

say "Number of keys in %local_h: " . scalar keys %local_h;

如果输出大于1,就说明哈希里有多个条目,这就是重复的原因。


解决办法

根据你的实际需求选择以下方案:

方案1:确保仅处理单个文件条目

如果%local_h只需要存储一组文件信息,直接获取哈希的唯一键即可,去掉foreach循环:

sub already_here {
    # 取出%local_h的唯一键
    my ($local) = keys(%local_h);
    my $target_name = $local_h{$local}{name};
    my $target_size = $local_h{$local}{size};
    
    my $FFR_rule = File::Find::Rule
        ->size($target_size)
        ->start( @volumes );
    
    while ( defined ( my $match = $FFR_rule->match ) ) {
        my ( $name, $path, $suffix ) = fileparse($match);
        # 用\Q\E包裹文件名,避免正则元字符导致匹配异常
        if ( $name =~ /\Q$target_name\E/ ) {
            say "\t\$name $name has been matched by size and name to:\n\t $path$name\n";
        } else {
            say "$match  Matched by size only\n";
        }
    }
}

方案2:处理多组条目但避免重复输出

如果%local_h确实需要存储多组文件信息,需要记录已经输出过的文件路径,避免重复打印:

sub already_here {
    # 哈希记录已输出的文件路径,避免重复
    my %seen;
    
    foreach my $local (keys(%local_h)) {
        my $target_name = $local_h{$local}{name};
        my $target_size = $local_h{$local}{size};
        
        my $FFR_rule = File::Find::Rule
            ->size($target_size)
            ->start( @volumes );
        
        while ( defined ( my $match = $FFR_rule->match ) ) {
            # 如果该文件已经输出过,直接跳过
            next if $seen{$match}++;
            
            my ( $name, $path, $suffix ) = fileparse($match);
            if ( $name =~ /\Q$target_name\E/ ) {
                say "\t\$name $name has been matched by size and name to:\n\t $path$name\n";
            } else {
                say "$match  Matched by size only\n";
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者Harry_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 22:43:11