我可以使用 find 命令将参数传递给 perl 吗?

Bri*_*ick 2 find perl

我有一个 perl 脚本

$ cat ~/script.pl
sub main {

    my ($file) = @_;

    <STUFF>

    }

}

foreach (@ARGV) {

    main($_);

}
Run Code Online (Sandbox Code Playgroud)

我想对目录下的~/script.pl每个.txt文件执行~/foo。我可以使用命令获取.txt文件列表~/foo

$ find ~/foo -type f -name \*.txt
Run Code Online (Sandbox Code Playgroud)

我可以以某种方式使用此命令将这些文件传递给我的脚本吗?

Rob*_*rtL 11

是的,有几种方法可以使用该find命令完成此操作。我将按照我认为对理解您的情况很重要的顺序列出一些。

  1. 您的脚本似乎接受多个文件名参数,因此使用该find命令完成此操作的最有效且几乎通用的方法是:

    find ~/foo -type f -name \*.txt -exec perl ~/script.pl {} +
    
    Run Code Online (Sandbox Code Playgroud)

    这将使用尽可能多的找到的文件名参数执行您的脚本。如果需要处理所有文件名,您的脚本将被多次调用。注意+行尾。

  2. 这是最原始也是最通用的方法。这对您的情况来说效率较低,因为它perl为找到的每个文件调用一次。这种用法从Unix 的早期就已经可用。请注意行尾的转义分号 ( \;)(与+上述相反)。

    find ~/foo -type f -name \*.txt -exec perl ~/script.pl {} \;
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在将-exec ... +语法添加到之前findxargs发明了该命令以帮助提高处理文件名列表或其他参数时的效率。这与-exec ... +上面的示例几乎相同:

    find ~/foo -type f -name \*.txt -print | xargs perl ~/script.pl
    
    Run Code Online (Sandbox Code Playgroud)

    如果您的实现支持它,您应该使用 的-print0选项find以及 的-0参数xargs。这会导致find在参数字符串之间打印空字符,并防止xargs在除空字符之外的任何内容上拆分参数。xargs如果您的文件名包含空格或其他一些特殊字符,这有助于防止错误地拆分参数。

    使用-exec ... +语法通常是一个更好的主意,因为find然后将文件名直接放入脚本的参数列表中,从而消除了一个过程,并避免了通过管道传输到xargs. 但是,xargs如果您需要对过程进行更多控制,则可能具有优势。请参阅xargs手册页。

  4. 您还可以查看find2perl使用相同参数的命令find并打印一个perl程序来执行相同的操作。然后,您可以将生成的perl代码合并到您的脚本中。在下面生成的脚本中,您将修改最后一行的下一行以调用您的函数而不是print.

    $ find2perl foo -type f -name \*.txt    # /*
    
    #[some preamble code removed for brevity]
    
    # Traverse desired filesystems
    File::Find::find({wanted => \&wanted}, 'foo');
    exit;
    
    sub wanted {
        my ($dev,$ino,$mode,$nlink,$uid,$gid);
    
        (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
        -f _ &&
        /^.*\.txt\z/s
        && print("$name\n");
    }   
    
    Run Code Online (Sandbox Code Playgroud)