用Perl查找文件 [英] Finding files with Perl

查看:188
本文介绍了用Perl查找文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

File :: Find 想要 子程序



比原来的标题(子程序的原型和前向声明)简单得多。我希望答案很简单,能够帮助我理解子程序/函数,原型和作用域以及 File :: Find 模块。



使用Perl,子程序几乎可以在任何地方出现,而且通常不需要进行前向声明(除非子程序声明原型,我不知道如何在标准在Perl中)。对于我通常用Perl做的事情,在运行 somefunction 的这些不同方式之间几乎没有区别:

  sub somefunction; #向前声明函数
& somefunction;
somefunction();
somefunction; #严重子文件中的裸字警告

我经常使用 find2perl 来生成代码,我可以入侵/入侵部分脚本。这可能是不好的风格,现在我的脏衣服是公开的,但它是这样的:-)对于 File :: Find wanted 函数是一个必需的子程序 - find2perl 创建它,并添加 sub wanted; 。有时,当我编辑脚本时,我将从 sub wanted 中删除​​ sub , code& wanted; 或 wanted(); 。但是,如果没有子想要; 向前声明表单我得到这个警告:

$ pre $ code >使用未初始化的值$ _在lstat在findscript.pl第29行

我的问题是:为什么这发生了,这是一个真正的问题?这是只是一个警告,但我想更好地理解它。




  • 文档和代码说 $ _ 被本地化在 sub wanted {} 中。为什么如果我使用 wanted(); 而不是子想要; 是未定义的?

  • 想要在某处使用原型吗?我在 Find / File.pm 中找不到明显的东西

  • 是否因为想要返回一个代码引用? (???)


    我的猜测是前向声明窗体初始化想要以某种方式使第一次使用没有一个空的默认变量。我想这应该是原型 - 甚至Perl原型,比如它们的存在 - 都可以工作。我尝试通过Perl源代码来了解当使用子函数 sub >而不是 function(),但在这一点上可能会超出我的范围。



    任何帮助加深加快)我的理解,这是非常赞赏。



    编辑:这是一个 find2perl 的输出创建了一个最近的堆栈  Overflow 示例脚本。如果从子想要的中删除​​,你应该得到相同的错误。



    编辑:正如我在下面的评论中指出的(但我也会在这里标记):几个月来,我一直在使用 Path :: Iterator :: Rule 而不是文件::查找。它需要 perl> 5.10 ,但是我从来不必在奇数的站点上部署产品代码,从不升级, 5.8。* 策略,所以 Path :: Iterator :: Rule 已经成为我从来不想做的模块之一。 Path :: Class 。干杯。

    解决方案

    我不是File :: Find的粉丝。它只是不正确。 find 命令不会返回文件列表,因此您必须在<$ c $>中使用非本地数组变量找到来捕获你找到的文件列表(不好),或者把你的整个程序放在你想要的子程序中(甚至更糟糕)。另外,单独的子例程意味着你的逻辑与你的 find 命令是分开的。这只是丑陋的。



    我在里面找到想要的子程序find find 命令。子程序保持查找。另外,我的非本地数组变量现在只是我的 find 命令的一部分,看起来不那么糟糕。 b

    下面是我如何处理 File :: Find - 假设我想要的文件具有 .pl 后缀:

      my @file_list; 
    find(sub {
    return unless -f;#必须是文件
    return,除非/\.pl$/;#必须以`.pl`结尾
    push @file_list,$ File :: Find :: name;
    },$ directory);

    #此时,@file_list包含我找到的所有文件。

    这与

      my @file_list; 

    find(\&wanted; $ directory);

    子通缉{
    return,除非-f;
    返回,除非/\.pl$/;
    push @file_list,$ File :: Find :: name;
    }

    #此时,@file_list包含了我找到的所有文件。

    在内线看起来更好。而且,它将我的代码保存在一起。另外,我的非本地数组变量看起来并不那么怪异。

    我也喜欢利用在这个特定的方式语法。通常,我不喜欢使用推断 $ _ ,但在这种情况下,它使代码更容易阅读。

      sub wanted {
    my $ file_name = $ _;
    if(-f $ file_name和$ file_name =〜/\.pl$/){
    push @file_list,$ File :: Find :: name;

    $ b $ / code $ / pre
    $ b $ File :: Find 不是很难使用。您只需要记住:


    • 当您找到不需要的文件时,可以使用 return code>包含没有目录的文件名,您可以使用code>来转到下一个文件。
    • $ _ 用于测试文件。
    • 文件的全名是 $ File :: Find :: name

    • 文件的目录是 $ File :: Find :: dir


    $ b $最简单的方法就是把你想要的文件压入一个数组,然后在你的程序中使用这个数组。


    File::Find and the wanted subroutine

    This question is much simpler than the original title ("prototypes and forward declaration of subroutines"!) lets on. I'm hoping the answer, however simple, will help me understand subroutines/functions, prototypes and scoping and the File::Find module.

    With Perl, subroutines can appear pretty much anywhere and you normally don't need to make forward declarations (except if the sub declares a prototype, which I'm not sure how to do in a "standard" way in Perl). For what I usually do with Perl there's little difference between these different ways of running somefunction:

    sub somefunction;  # Forward declares the function
    &somefunction; 
    somefunction();
    somefunction;   # Bare word warning under `strict subs`
    

    I often use find2perl to generate code which I crib/hack into parts of scripts. This could well be bad style and now my dirty laundry is public, but so be it :-) For File::Find the wanted function is a required subroutine - find2perl creates it and adds sub wanted; to the resulting script it creates. Sometimes, when I edit the script I'll remove the "sub" from sub wanted and it ends up as &wanted; or wanted();. But without the sub wanted; forward declaration form I get this warning:

    Use of uninitialized value $_ in lstat at findscript.pl line 29
    

    My question is: why does this happen and is it a real problem? It is "just a warning", but I want to understand it better.

    • The documentation and code say $_ is localized inside of sub wanted {}. Why would it be undefined if I use wanted(); instead of sub wanted;?
    • Is wanted using prototypes somewhere? Am I missing something obvious in Find/File.pm?
    • Is it because wanted returns a code reference? (???)

    My guess is that the forward declaration form "initializes" wanted in some way so that the first use doesn't have an empty default variable. I guess this would be how prototypes - even Perl prototypes, such as they exist - would work as well. I tried grepping through the Perl source code to get a sense of what sub is doing when a function is called using sub function instead of function(), but that may be beyond me at this point.

    Any help deepening (and speeding up) my understanding of this is much appreciated.

    EDIT: Here's a recent example script here on Stack Overflow that I created using find2perl's output. If you remove the sub from sub wanted; you should get the same error.

    EDIT: As I noted in a comment below (but I'll flag it here too): for several months I've been using Path::Iterator::Rule instead of File::Find. It requires perl >5.10, but I never have to deploy production code at sites with odd, "never upgrade", 5.8.* only policies so Path::Iterator::Rule has become one of those modules I never want to do with out. Also useful is Path::Class. Cheers.

    解决方案

    I'm not a big fan of File::Find. It just doesn't work right. The find command doesn't return a list of files, so you either have to use a non-local array variable in your find to capture your list of files you've found (not good), or place your entire program in your wanted subroutine (even worse). Plus, the separate subroutine means that your logic is separate from your find command. It's just ugly.

    What I do is inline my wanted subroutine inside my find command. Subroutine stays with the find. Plus, my non-local array variable is now just part of my find command and doesn't look so bad

    Here's how I handle the File::Find -- assuming I want files that have a .pl suffix:

    my @file_list;
    find ( sub {
        return unless -f;       #Must be a file
        return unless /\.pl$/;  #Must end with `.pl` suffix
        push @file_list, $File::Find::name;
    }, $directory );
    
    # At this point, @file_list contains all of the files I found.
    

    This is exactly the same as:

    my @file_list;
    
    find ( \&wanted, $directory );
    
    sub wanted {
        return unless -f;
        return unless /\.pl$/;
        push @file_list, $File::Find::name;
    }
    
    # At this point, @file_list contains all of the files I found.
    

    In lining just looks nicer. And, it keep my code together. Plus, my non-local array variable doesn't look so freaky.

    I also like taking advantage of the shorter syntax in this particular way. Normally, I don't like using the inferred $_, but in this case, it makes the code much easier to read. My original Wanted is the same as this:

    sub wanted {
        my $file_name = $_;
        if ( -f $file_name and $file_name =~ /\.pl$/ ) {
            push @file_list, $File::Find::name;
        }
    }
    

    File::Find isn't that tricky to use. You just have to remember:

    • When you find a file you don't want, you use return to go to the next file.
    • $_ contains the file name without the directory, and you can use that for testing the file.
    • The file's full name is $File::Find::name.
    • The file's directory is $File::Find::dir.

    And, the easiest way is to push the files you want into an array, and then use that array later in your program.

    这篇关于用Perl查找文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆