如何从perl中读取数组中的文件?

时间:2011-05-18 03:03:48

标签: arrays perl file

我已将包含文件的目录读入数组。现在的问题是我想打开文件并在它们之间用一行显示它们的内容。

例如,我想打开file1.txt和file2.txt,并显示如下内容:

很高兴见到你 - 文件1

你好吗? - 文件2

代码是:

sub openFile{
   opendir(fol, "folder/details");
   my @files= readdir(fol); 
   my @FilesSorted = sort(@files);
   foreach my $EachFile (@FilesSorted) {
      print $EachFile . "\n";
   } 
}

6 个答案:

答案 0 :(得分:2)

如果你只想显示文件中的所有行(正如你的代码似乎试图做的那样),而没有任何关于哪个行来自哪个文件的指示,那么就有一个涉及预定义变量的技巧@ARGV

sub openFile {
    opendir(fol, "folder/details");
    @ARGV = sort(readdir(fol));
    close fol;
    while (<>) {
        print "$_\n";
    }
}

如果您需要打印文件名,则必须明确打开每个文件:

sub openFile {
    opendir(fol, "folder/details");
    my @files = sort(readdir(fol));
    close fol;
    while ($file = shift @files) {
        open(FILE, $file);
        while (<FILE>) {
            print "$_\n";
        }
        close FILE;
    }
}

答案 1 :(得分:2)

另一个例子,有一些错误检查和跳过子目录:

sub print_all_files {
  my $dir = shift;
  opendir(my $dh, $dir) || die "Can't read [$dir]: $!";
  while(defined(my $file = readdir $dh)) {
    next unless -f "$dir/$file"; # Ignore subdirs and . and ..
    open(my $fh, "<", "$dir/$file") || die "Can't read [$dir/$file]: $!";
    print while readline($fh);
    print "\n"; # add an extra line
  }
} 

print_all_files("folder/details");

答案 2 :(得分:1)

尝试

sub openFile{
   opendir(fol, "folder/details");
   my @files= readdir(fol); 
   my @FilesSorted = sort(@files);
   foreach my $EachFile (@FilesSorted) {
      if($EachFile ne "." && $EachFile ne ".." && !(-d $EachFile)) { #important to skip the directories 
        open IT $EachFile || die "unable to read ".$EachFile."\n"; # open file
        while($line = <IT>) {  # print content in file
           print "$line\n";
        }
        close(IT); # close file
        print "-->$EachFile\n";  # print file name
   } 
}

答案 3 :(得分:1)

您可以使用File::Util之类的模块简化目录读取代码。它或类似的其他模块将提供一些便利:错误检查;过滤掉不需要的目录内容(如...子目录);按类型选择内容(例如,只是文件或目录);并将根路径附加到内容。

use strict;
use warnings;
use File::Util qw();

my $dir = 'folder/details';
my $file_util = File::Util->new;
my @files = $file_util->list_dir($dir, qw(--with-paths --no-fsdots --files-only));

for my $f (@files){
    local @ARGV = ($f);
    print while <>;
    print "\n";
}

如果您不想使用其他模块,可以获取如下文件名:

opendir(my $dh, $dir) or die $!;
my @files = grep -f, map("$dir/$_", readdir $dh);

答案 4 :(得分:1)

这可以是一个独立的计划吗?

#! /usr/bin/env perl

use strict;
use warnings;

die "$0: no arguments allowed\n" if @ARGV;

my $dir = "folder/details";
opendir my $dh, $dir or die "$0: opendir $dir: $!";

while (defined(my $file = readdir $dh)) {
  my $path = $dir . "/" . $file;
  push @ARGV, $path if -f $path;
}

@ARGV = sort @ARGV;
while (<>) {
  print;
}
continue {
  print "\n" if eof && @ARGV;
}

备注

  • defined检查从readdir返回的每个值是必要的,以处理Perl中名称为false值的文件,例如0
  • 您的意图是在folder/details中写入文件的内容,因此还需要使用-f测试过滤普通文件。
  • Perl在while (<>) { ... }中的内置处理将参数从@ARGV的前面移开。 eof - 没有括号!{continue子句中的-test检测每个文件的结尾,并将换行符打印为文件之间的分隔符,而不是终结符。

答案 5 :(得分:0)

跟进Greg Bacon's回答(重新:“这可以是一个独立的程序吗?”),如果你仍然想在openFile子程序中使用它,你可以在那里使用相同的循环:< / p>

sub openFile{
  opendir(fol, "folder/details");
  my @files= readdir(fol); 
  my @FilesSorted = sort(@files);
  local @ARGV = @FilesSorted;
  while (<>) {
    print;
  } 
  continue {
    print "\n" if eof && @ARGV;
  } 
}

注意local @ARGV的使用(如FMc's answer中所示):这将保留子例程外部的任何全局参数列表,并在退出时恢复该值。