【问题标题】:How can I get a list of all files with a certain extension from a specific directory?如何从特定目录获取具有特定扩展名的所有文件的列表?
【发布时间】:2010-12-03 09:02:43
【问题描述】:

我正在使用此代码获取特定目录中所有文件的列表:

opendir DIR, $dir or die "cannot open dir $dir: $!";
my @files= readdir DIR;
closedir DIR;

如何修改此代码或在其中附加一些内容,使其仅查找文本文件并仅加载带有文件名前缀的数组?

示例目录内容:

.
..
923847.txt
98398523.txt
198.txt
deisi.jpg
oisoifs.gif
lksdjl.exe

示例数组内容:

files[0]=923847 
files[1]=98398523
files[2]=198

【问题讨论】:

  • 还可以考虑为目录句柄使用词法变量:opendir my $dirh, $dir_path or die "cannot open dir $dir: $!";

标签: perl directory


【解决方案1】:
my @files = glob "$dir/*.txt";
for (0..$#files){
  $files[$_] =~ s/\.txt$//;
}

【讨论】:

  • 知道如何将目录正则表达式输出吗?我的输出是 /dir/dir/dir/923847... 我怎样才能得到 923847?
  • glob 在这里添加了额外的工作。见stackoverflow.com/questions/1506801/…
【解决方案2】:

改一行就够了:

my @files= map{s/\.[^.]+$//;$_}grep {/\.txt$/} readdir DIR;

【讨论】:

    【解决方案3】:

    如果你可以使用 Perl 5.10 的新特性,我会这样写。

    use strict;
    use warnings;
    use 5.10.1;
    use autodie; # don't need to check the output of opendir now
    
    my $dir = ".";
    
    {
      opendir my($dirhandle), $dir;
      for( readdir $dirhandle ){ # sets $_
        when(-d $_ ){ next } # skip directories
        when(/^[.]/){ next } # skip dot-files
    
        when(/(.+)[.]txt$/){ say "text file: ", $1 }
        default{
          say "other file: ", $_;
        }
      }
      # $dirhandle is automatically closed here
    }
    

    或者如果您有非常大的目录,您可以使用while 循环。

    {
      opendir my($dirhandle), $dir;
      while( my $elem = readdir $dirhandle ){
        given( $elem ){ # sets $_
          when(-d $_ ){ next } # skip directories
          when(/^[.]/){ next } # skip dot-files
    
          when(/(.+)[.]txt$/){ say "text file: ", $1 }
          default{
            say "other file: ", $_;
          }
        }
      }
    }
    

    【讨论】:

      【解决方案4】:

      这是我发现的使用 glob 函数的最简单方法(如人类可读):

       # Store only TXT-files in the @files array using glob
       my @files = grep ( -f ,<*.txt>);
       # Write them out
       foreach $file (@files) {
        print "$file\n";
       }
      

      此外,“-f”确保只有实际文件(而不是目录)存储在数组中。

      【讨论】:

      • 为什么要回滚编辑? foreach $file 不是严格安全的。如果您更喜欢foreach 而不是for,为什么不喜欢foreach my $file
      • 当您不知道为什么首先发布它的原因时,为什么要编辑别人的旧东西?我什至不知道我三年多前写这段代码的原因,但由于我有测试东西的习惯,它可能工作得很好,而且我可能没有添加严格的原因声明要么。然而,这是否意味着我应该接受随机编辑,我什至想花时间测试它吗?一定不行!这就是为什么我发现直接回滚要安全得多。
      • 为了清楚起见,不是我编辑的,我只是看到编辑并认为它改进了答案。你使用词汇@files 然后使用全局$file,这很奇怪。
      • 像英语一样阅读:对于文件列表中的每个文件,对列表中的每个文件执行一些操作(例如,打印每个文件条目)。我喜欢英语,因为大多数人都懂。我仍然不会尝试自己改进它,并且我将回滚所有其他尝试,因为我不想测试其他人对我的代码的奇怪更改。但是,如果真的那么糟糕,我可能会完全删除我的答案。相反,请使用我的代码并发布您自己的答案。我的意思是,它不像受版权保护或其他任何东西,所以请继续。 :)
      • > 我也没有在严格声明中添加可能是有原因的。从字面上看,我们没有任何不严格的理由。投反对票。
      【解决方案5】:

      要仅获取“.txt”文件,您可以使用文件测试运算符(-f :常规文件)和正则表达式。

      my @files = grep { -f && /\.txt$/ } readdir $dir;
      

      否则,您可以只查找文本文件,使用 perl 的 -T(ascii 文本文件测试运算符)

      my @files = grep { -T } readdir $dir;
      

      【讨论】:

      • -T 用于测试是否有“文本文件”
      • 好点;来自运算符 (perldoc.perl.org/5.8.8/perlfunc.html) 的 perldoc 页面,“-T 文件是一个 ASCII 文本文件(启发式猜测)。”如果他正在寻找“.txt”文件,这将完全按照他的要求进行,无需猜测。
      【解决方案6】:

      就用这个吧:

      my @files = map {-f && s{\.txt\z}{} ? $_ : ()} readdir DIR;
      

      【讨论】:

      • 对我不起作用... ""名称 "main::DIR" 只使用了一次:fileOpsDS.pl 第 19 行可能有错字。"" ""readdir() 尝试在无效的 dirhandle 上fileOpsDS.pl 第 19 行的 DIR。""
      猜你喜欢
      • 2019-11-03
      • 2021-06-08
      • 1970-01-01
      • 2019-06-14
      • 2013-09-20
      • 2018-04-27
      • 1970-01-01
      • 1970-01-01
      • 2014-09-21
      相关资源
      最近更新 更多