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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18252875/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 06:15:46  来源:igfitidea点击:

How to get Perl to loop over all files in a directory?

linuxperlbash

提问by Sandra Schlichting

I have a Perl script with contains

我有一个包含的 Perl 脚本

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

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

close FILE;

and I would like to run this script on all .ppfiles in a directory, so I have written a wrapper script in Bash

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

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

Question

Is it possible to avoid the wrapper script and have the Perl script do it instead?

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

回答by amon

Yes.

是的。

The for f in ...;translates to the Perl

for f in ...;转换为Perl的

  • for my $f (...) { ... }(in the case of lists) or
  • while (my $f = ...) { ... }(in the case of iterators).
  • for my $f (...) { ... }(在列表的情况下)或
  • while (my $f = ...) { ... }(在迭代器的情况下)。

The glob expression that you use (/etc/puppet/nodes/*.pp) can be evaluated inside Perl via the globfunction: glob '/etc/puppet/nodes/*.pp'.

您使用的 glob 表达式 ( /etc/puppet/nodes/*.pp) 可以在 Perl 内部通过glob函数:求值glob '/etc/puppet/nodes/*.pp'

Together with some style improvements:

连同一些样式改进:

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;
}

Then:

然后:

$ /etc/puppet/nodes/brackets.pl

回答by Jason Orendorff

This isn't quite what you asked, but another possibility is to use <>:

这不是你问的,但另一种可能性是使用<>

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

Then you would put the filenames on the command line, like this:

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

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

Perl opens and closes each file for you. (Inside the loop, the current filename and line number are $ARGVand $.respectively.)

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

回答by David W.

Jason Orendorffhas the right answer:

Jason Orendorff 给出了正确的答案:

From Perlop (I/O Operators)

来自Perlop(I/O 操作员)

The null filehandle <> is special: it can be used to emulate the behavior of sed and awk, and any other Unix filter program that takes a list of filenames, doing the same to each line of input from all of them. Input from <> comes either from standard input, or from each file listed on the command line.

空文件句柄 <> 是特殊的:它可以用来模拟 sed 和 awk 的行为,以及任何其他接受文件名列表的 Unix 过滤程序,对来自所有文件名的每一行输入执行相同的操作。<> 的输入要么来自标准输入,要么来自命令行上列出的每个文件。

This doesn't require opendir. It doesn't require using globsor hard coding stuff in your program. This is the natural way to read in all files that are found on the command line, or piped from STDIN into the program.

这不需要opendir. 它不需要globs在您的程序中使用或硬编码的东西。这是读入在命令行上找到的所有文件或从 STDIN 管道传输到程序中的所有文件的自然方式。

With this, you could do:

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

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

or

或者

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

or even:

甚至:

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

回答by Sedi

I would suggest to put all filenames to array and then use this array as parameters list to your perl method or script. Please see following code:

我建议将所有文件名放入数组,然后将此数组用作 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);

Now you can pass \@files as parameter to any perl method.

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

回答by Sibster

take a look at this documentationit explains all you need to know

看看这个文档,它解释了你需要知道的一切

#!/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;

回答by michael501

   my @x =   <*>;  

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

    };

回答by Hunter McMillen

Perl can shell out to execute system commands in various ways, the most straightforward is using backticks ``

Perl可以通过多种方式shell out来执行系统命令,最直接的就是使用反引号``

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;
}

(Note: you should alwaysuse strict;and use warnings;)

(注意:你应该总是use strict;use warnings;