您好我想在不知道目录名的情况下阅读目录和子目录。当前目录是" 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";
}
答案 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
用于按您想要的顺序排列这些目录<"$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`