【问题标题】:How do I get a directory listing in Perl? [duplicate]如何在 Perl 中获取目录列表? [复制]
【发布时间】:2010-09-17 08:05:19
【问题描述】:

我想在 Perl 程序中执行 ls 作为 CGI 脚本的一部分。为此,我使用了exec(ls),但这不会从exec 调用中返回。

有没有更好的方法在 Perl 中获取目录列表?

【问题讨论】:

  • 系统(“ls”);会这样做。

标签: perl list directory


【解决方案1】:

Exec 根本不返回。如果需要,请使用系统。

如果你只是想读取一个目录,open/read/close-dir 可能更合适。

opendir my($dh), $dirname or die "Couldn't open dir '$dirname': $!";
my @files = readdir $dh;
closedir $dh;
#print files...

【讨论】:

  • 检查系统命令的返回值:opendir... or die "... $!"或“使用autodie;”默认情况下使它们致命。我知道这只是吹毛求疵,但是当您向初学者提供建议时,这对他们来说是重要的一课。
  • 如果有人想知道为什么不检查 readdir 和 closedir:两者都只有一个可能的错误,“无效的目录句柄”。由于我自己打开并检查了它,我可以放心地假设它是有效的。此外,在列表上下文中,无论如何都无法检查 readddir。
  • 如果你不想要点文件,你可以这样做:my @files = grep { !/^\./ } readdir $dh;
  • 如果你想要以点开头的文件,而不是...(对于当前目录和父目录),那么你想要:my @files = grep { !/^\.\.?$/ } readdir $dh;
【解决方案2】:

其他人似乎都停留在问​​题的执行部分。

如果您想要目录列表,请使用 Perl 的内置 globopendir。您不需要单独的流程。

【讨论】:

  • 具体来说,glob 完全符合您的要求:返回文件夹中文件名的数组。
【解决方案3】:

exec 不会将控制权交还给 perl 程序。 system 会,但它不返回 ls 的结果,它返回一个状态码。 标记 `` 会给你我们命令的输出,但被一些人认为是不安全的。

使用内置的 dir 函数。 opendir、readdir 等。

http://perldoc.perl.org/functions/opendir.html

http://perldoc.perl.org/functions/readdir.html

【讨论】:

    【解决方案4】:

    为了获得系统命令的输出,您需要使用反引号。

    $listing = `ls`;
    

    然而,Perl 擅长自己处理目录。我建议使用 File::Find::Rule。

    【讨论】:

      【解决方案5】:

      使用 Perl 通配符:

      my $dir = </dir/path/*> 
      

      【讨论】:

        【解决方案6】:

        又一个例子:

        chdir $dir or die "Cannot chroot to $dir: $!\n";
        my @files = glob("*.txt");
        

        【讨论】:

          【解决方案7】:

          编辑:哎呀!我以为您只是想要目录列表...删除“目录”调用以使该脚本执行您想要的操作...

          在我看来,使用文件句柄是错误的做法。以下是使用 File::Find::Rule 查找指定目录中所有目录的示例。对于你正在做的事情,这似乎有点过头了,但后来它可能是值得的。

          首先,我的单行解决方案:

          File::Find::Rule->maxdepth(1)->directory->in($base_dir);
          

          现在是带有 cmets 的更详细的版本。如果你安装了 File::Find::Rule,你应该可以运行这个没有问题。不要害怕 CPAN。

          #!/usr/bin/perl
          
          use strict;
          use warnings;
          
          # See http://search.cpan.org/~rclamp/File-Find-Rule-0.32/README
          use File::Find::Rule;
          
          # If a base directory was not past to the script, assume current working director
          my $base_dir = shift // '.';
          my $find_rule = File::Find::Rule->new;
          
          # Do not descend past the first level
          $find_rule->maxdepth(1);
          
          # Only return directories
          $find_rule->directory;
          
          # Apply the rule and retrieve the subdirectories
          my @sub_dirs = $find_rule->in($base_dir);
          
          # Print out the name of each directory on its own line
          print join("\n", @sub_dirs);
          

          【讨论】:

          • +1 作为 File::Find::Rule 摇摆不定
          【解决方案8】:

          我建议你看看IPC::Open3。与系统或反引号相比,它允许对生成的进程进行更多的控制。

          【讨论】:

            【解决方案9】:

            在 Linux 上,我更喜欢 find:

            my @files = map { chomp; $_ } `find`;
            

            【讨论】:

            • 如果您不仅要列出目录,而且要查找具有某些条件的文件,这将特别有用。比如说你想在过去 2 天内修改文件:我的 @recentFiles = map { chomp; $_ } find $theDir -maxdepth 1 -type f -mtime -2;
            猜你喜欢
            • 1970-01-01
            • 2010-09-23
            • 2012-04-22
            • 1970-01-01
            • 2011-07-15
            • 1970-01-01
            • 2019-01-02
            • 1970-01-01
            • 2022-01-02
            相关资源
            最近更新 更多