如何让Perl循环遍历目录中的所有文件?

时间:2013-08-15 12:42:48

标签: linux perl bash

我有一个包含

的Perl脚本
open (FILE, '<', "$ARGV[0]") || die "Unable to open $ARGV[0]\n";

while (defined (my $line = <FILE>)) {
  # do stuff
}

close FILE;

我想在目录中的所有.pp文件上运行此脚本,所以我在Bash中编写了一个包装器脚本

#!/bin/bash
for f in /etc/puppet/nodes/*.pp; do
    /etc/puppet/nodes/brackets.pl $f
done

问题

是否可以避免使用包装器脚本并让Perl脚本代替它?

7 个答案:

答案 0 :(得分:8)

for f in ...;转换为Perl

  • for my $f (...) { ... }(在列表的情况下)或
  • while (my $f = ...) { ... }(在迭代器的情况下)。

您使用的glob表达式(/etc/puppet/nodes/*.pp)可以通过glob function glob '/etc/puppet/nodes/*.pp'在Perl中进行评估。

与一些风格改进一起:

use strict; use warnings;
use autodie;  # automatic error handling

while (defined(my $file = glob '/etc/puppet/nodes/*.pp')) {
  open my $fh, "<", $file;  # lexical file handles, automatic error handling

  while (defined( my $line = <$fh> )) {
    do stuff;
  }
  close $fh;
}

然后:

$ /etc/puppet/nodes/brackets.pl

答案 1 :(得分:5)

这不是你提出的要求,但另一种可能性是使用<>

while (<>) {
    my $line = $_;
    # do stuff
}

然后你将文件名放在命令行上,如下所示:

/etc/puppet/nodes/brackets.pl /etc/puppet/nodes/*.pp

Perl会为您打开和关闭每个文件。 (在循环内部,当前文件名和行号分别为$ARGV$.。)

答案 2 :(得分:2)

Jason Orendorff有正确答案:

来自Perlop (I/O Operators)

  

null文件句柄&lt;&gt;很特别:它可以用来模拟sed和awk的行为,以及任何其他带有文件名列表的Unix过滤器程序,对所有输入的每一行做同样的事情。来自&lt;&gt;的输入来自标准输入,或来自命令行中列出的每个文件。

这不需要opendir。它不需要在程序中使用globs或硬编码。这是读取命令行中所有文件或从STDIN传输到程序中的所有文件的自然方式。

有了这个,你可以这样做:

$ myprog.pl /etc/puppet/nodes/*.pp

$ myprog.pl /etc/puppet/nodes/*.pp.backup

甚至:

$ cat /etc/puppet/nodes/*.pp | myprog.pl

答案 3 :(得分:1)

看看this documentation它解释了你需要知道的所有内容

#!/usr/bin/perl

use strict;
use warnings;

my $dir = '/tmp';

opendir(DIR, $dir) or die $!;

while (my $file = readdir(DIR)) {
# We only want files
next unless (-f "$dir/$file");

# Use a regular expression to find files ending in .pp


   next unless ($file =~ m/\.pp$/);
open (FILE, '<', $file) || die "Unable to open $file\n";

while (defined (my $line = <FILE>)) {
  # do stuff
}
}

closedir(DIR);
exit 0;

答案 4 :(得分:1)

我建议将所有文件名放到数组中,然后将此数组用作perl方法或脚本的参数列表。请参阅以下代码:

use Data::Dumper
$dirname = "/etc/puppet/nodes";
opendir ( DIR, $dirname ) || die "Error in opening dir $dirname\n";

my @files = grep {/.*\.pp/} readdir(DIR);
print Dumper(@files);

closedir(DIR);

现在您可以将\ @files作为参数传递给任何perl方法。

答案 5 :(得分:0)

   my @x =   <*>;  

   foreach ( @x ) {
      chomp;
      if ( -f "$_" ) {
         print "process $_\n";  
         # do stuff
         next;
      };

    };

答案 6 :(得分:-2)

Perl可以以各种方式执行系统命令,最直接的是使用反引号``

use strict;
use warnings FATAL => 'all';

my @ls = `ls /etc/puppet/nodes/*.pp`;
for my $f ( @ls ) {
   open (my $FILE, '<', $f) || die "Unable to open $f\n";

   while (defined (my $line = <$FILE>)) {
      # do stuff
   }
   close $FILE;
}

(注意:您应始终 use strict;use warnings;