如何在不知道perl中的目录名的情况下读取目录和子目录?

时间:2013-12-12 18:33:15

标签: perl

您好我想在不知道目录名的情况下阅读目录和子目录。当前目录是" D:/ Temp"。 '温度'有子目录,如' A1',' A2'。再次' A1'有子目录,如' B1',' B2'。再次' B1'有子目录,如' C1',' C2'。 Perl脚本不知道这些目录。所以它必须首先找到目录,然后在dir' C1'中一次读取一个文件。一旦所有文件被读入' C1'它应该改为dir' C2'。我尝试使用下面的代码,我不想读取数组中的所有文件(@files)但是需要一个文件。在数组@dir元素应该是休闲。

$dir[0] = "D:/Temp/A1/B1/C1"
$dir[1] = "D:/Temp/A1/B1/C2"
$dir[2] = "D:/Temp/A1/B2/C1"

以下是我尝试的代码。

    use strict;
    use File::Find::Rule;
    use Data::Dumper;

    my $dir = "D:/Temp";
    my @dir = File::Find::Rule->directory->in($dir);
    print Dumper (\@dir);
    my $readDir = $dir[3];
    opendir ( DIR, $readDir ) || die "Error in opening dir $readDir\n";
    my @files = grep { !/^\.\.?$/ } readdir DIR;
    print STDERR "files: @files \n\n";

    for my $fil (@files) {
        open (F, "<$fil");
        read (F, my $data);
        close (F);
        print "$data";
    }

5 个答案:

答案 0 :(得分:3)

use File::Find;

use strict;
use warnings;

my @dirs;
my %has_children;

find(sub {
    if (-d) {
        push @dirs, $File::Find::name;
        $has_children{$File::Find::dir} = 1;
    }
}, 'D:/Temp');

my @ends = grep {! $has_children{$_}} @dirs;

print "$_\n" for (@ends);

答案 1 :(得分:2)

也许以下内容会有所帮助:

use strict;
use warnings;
use File::Find::Rule;

my $dir = "D:/Temp";
local $/;

my @dirs =
  sort File::Find::Rule->exec( sub { File::Find::Rule->directory->in($_) == 1 }
  )->directory->in($dir);

for my $dir (@dirs) {
    for my $file (<"$dir/*">) {
        open my $fh, '<', $file or die $!;
        my $data = <$fh>;
        close $fh;
        print $data;
    }
}
  • local $/;让我们将文件的内容 slurp 变成一个变量。如果您只想阅读第一行,请将其删除。
  • sub中的exec()用于仅传递不包含目录的目录
  • sort用于按您想要的顺序排列这些目录
  • 文件glob <"$dir/*">用于获取每个目录中的文件

编辑:修改了代码以仅查找“终端目录”。感谢DavidRR对此规范的澄清。

答案 2 :(得分:2)

您的目标:查找自己拥有子目录的目录的绝对路径。

我会将那些感兴趣的目录称为终端目录。这是函数的原型,我相信它提供了您正在寻找的便利。该函数将其结果作为列表返回。

my @list = find_terminal_directories($full_or_partial_path);

这是find_terminal_directories()的实现。请注意,此实现需要使用任何全局变量。另请注意使用名为递归的私有帮助函数。

在我的Windows 7系统上,对于输入目录 C:/ Perl / lib / Test ,我得到了输出:

== List of Terminal Folders ==
c:/Perl/lib/Test/Builder/IO
c:/Perl/lib/Test/Builder/Tester
c:/Perl/lib/Test/Perl/Critic

== List of Files in each Terminal Folder: ==
c:/Perl/lib/Test/Builder/IO/Scalar.pm
c:/Perl/lib/Test/Builder/Tester/Color.pm
c:/Perl/lib/Test/Perl/Critic/Policy.pm

<强>实施

#!/usr/bin/env perl

use strict;
use warnings;
use Cwd qw(abs_path getcwd);

my @dir_list = find_terminal_directories("C:/Perl/lib/Test");
print "== List of Terminal Directories ==\n";
print join("\n", @dir_list), "\n";

print "\n== List of Files in each Terminal Directory: ==\n";
for my $dir (@dir_list) {
    for my $file (<"$dir/*">) {
        print "$file\n";
        open my $fh, '<', $file or die $!;
        my $data = <$fh>;  # slurp entire file contents into $data
        close $fh;

        # Now, do something with $data !
    }
}

sub find_terminal_directories {
    my $rootdir = shift;

    my @wanted;
    my $cwd = getcwd();
    chdir $rootdir;
    find_terminal_directories_helper(".", \@wanted);
    chdir $cwd;
    return @wanted;
}

sub find_terminal_directories_helper {
    my ($dir, $wanted) = @_;
    return if ! -d $dir;
    opendir(my $dh, $dir) or die "open directory error!";
    my $count = 0;
    foreach my $child (readdir($dh)) {
        my $abs_child = abs_path($child);
        next if (! -d $child || $child eq "." || $child eq "..");
        ++$count;
        chdir $child;
        find_terminal_directories_helper($abs_child, $wanted);  # recursion!
        chdir "..";
    }
    push @$wanted, abs_path($dir) if ! $count;  # no sub-directories found!
}

答案 3 :(得分:0)

我会使用File::Find

示例脚本:

#!/usr/bin/perl

use strict; 
use warnings;

use File::Find;

my $dir = "/home/chris";

find(\&wanted, $dir);

sub wanted {
    print "dir: $File::Find::dir\n";
    print "file in dir: $_\n";
    print "complete path to file: $File::Find::name\n";
}

输出:

$ test.pl
dir: /home/chris/test_dir
file in dir: test_dir2
complete path to file: /home/chris/test_dir/test_dir2
dir: /home/chris/test_dir/test_dir2
file in dir: foo.txt
complete path to file: /home/chris/test_dir/test_dir2/foo.txt
...

答案 4 :(得分:-1)

使用反引号,将子目录和文件写入名为filelist的文件:

`ls -R $dir > filelist`