perl,使用 File::Find 是否可以在该函数之外修改数据结构



>我正在尝试遍历每个文件夹中的文件并从该文件中获取信息并将其更新为数组例如。

use File::Find;
sub main
{
    my @names = ();
    my $dir = "mydir";        
    # will traverse directories and look for file 'list.txt'
    ### now, is it possible to update @names while traversing using find?
    find(&getNames(), $dir);
}
sub getNames
{
    #I tried to take names as argument but it doesn't seem to work..
    if (-f $_ && $_ eq 'list.txt')
    {
         #update names possible?
    }
}

是否可以在使用 File::Find 遍历时更新数据结构? 而且我尽量不使用全局变量。

是的,使用称为闭包或匿名子例程的漂亮功能是可能的。

尝试将查找调用更改为如下所示的内容:

find( sub { getNames(@names, @_) }, $dir);

在这里,我定义了一个闭包,它反过来调用你的函数"getNames",引用你的数据结构作为第一个参数,后跟 find 本身提供的任何其他参数。

在 getNames 中,可以检索数据结构作为第一个参数:

sub getNames
{
    my @names = shift;
    ...

随心所欲地使用数组,其他任何内容都不需要更改。

另外,阅读 Perl 中的闭包: http://perldoc.perl.org/perlfaq7.html#What%27s-a-closure%3F

您可能会

发现使用基于迭代器的文件查找模块(如 File::Next )更容易。

#!/usr/bin/perl
use warnings;
use strict;
use File::Next;
my $iterator = File::Next::files( '.' );
while ( my $file = $iterator->() ) {
    if ( $file eq 'list.txt' ) {
        print "Found list.txtn";
    }
}
这样做

,您不必担心您所在的功能范围。

您也可以让 File::Next 为您执行过滤:

my $iterator = File::Next::files( {
        file_filter => sub { $_ eq 'list.txt' },
    }, '.' );
while ( my $file = $iterator->() ) {
    # No need to check, because File::Next does the filtering
    print "Found list.txtn";
}

如果你不需要其他地方getNames,那么你可以在main内部将此子例程定义为匿名子例程。 @names在此子例程中可用。

use File::Find;
sub main
{
    my @names = ();
    my $dir = "mydir";        
    my $getNames = sub
    {
        if (-f $_ && $_ eq 'list.txt')
        {
             #update names possible? -> yes, @names is visible here
        }
    };
    # will traverse directories and look for file 'list.txt'
    ### now, is it possible to update @names while traversing using find?
    find($getNames, $dir);
}