我编写了一个例程来读取两个文件夹及其所有子文件夹中包含的文件的所有名称和大小。根文件夹名称在命令行参数中提供,并且每个文件夹都在for循环中进行处理,详细信息将输出到两个文件夹中每个文件夹的单独文件中。但是我发现只有两个根文件夹中的文件的文件名/大小正在输出,我无法更改为子文件夹并重复该过程,因此子目录中的文件将被忽略。调试跟踪显示chdir命令从未执行过,因此我的评估有问题,但是我看不到它是什么。 代码看起来像这样
#!/usr/bin/perl
#!/usr/local/bin/perl
use strict;
use warnings;
my $dir = $ARGV[0];
opendir(DIR, $dir) or die "Could not open directory '$dir' $!";
my @subdirs = readdir(DIR) or die "Unable to read directory '$dir': $!";
for (my $loopcount = 1; $loopcount < 3; $loopcount = $loopcount + 1) {
my $filename = 'FileSize_'.$dir.'.txt';
open (my $fh, '>', $filename) or die "Could not open file '$filename' $!";
for my $subdir (sort @subdirs) {
unless (-d $subdir) {
# Ignore Sub-Directories in this inner loop
# only process files
# print the file name and file size to the output file
print "Processing files\n";
my $size = -s "$dir/$subdir";
print $fh "$subdir"," ","$size\n";
}
elsif (-s "$dir/$subdir") {
# We are here because the entry is a sub-folder and not a file
# if this sub-folder is non-zero size, i.e has files then
# change to this directory and repeat the outer for loop
chdir $subdir;
print "Changing to directory $subdir\n";
print "Processing Files in $subdir\n";
};
}
# We have now processed all the files in First Folder and all it's subdirecorries
# Now assign the second root directory to the $dir variable and repeat the loop
print "Start For Next Directory\n";
$dir = $ARGV[1];
opendir(DIR, $dir) or die "Could not open directory '$dir' $!";
@subdirs = readdir(DIR) or die "Unable to read directory '$dir': $!";;
}
exit 0;
命令行调用为“ perl FileComp.pl DiskImage DiskImage1” 但是仅输出DiskImage和DiskImage1根文件夹中文件的文件名和文件大小,子文件夹中的所有文件都将被忽略。 永远不会满足更改为“ elseif”条件的代码,也永远不会执行该代码,因此那里存在错误。 预先感谢您的任何建议。
答案 0 :(得分:3)
此检查很可能总是错误的,因为您正在寻找错误的东西。
unless (-d $subdir) {
$subdir
是$dir
中文件或目录的文件名,因此要访问它,您需要使用$dir/$subdir
的完整相对路径,就像在这里所做的一样:>
my $size = -s "$dir/$subdir";
如果您确实修复了unless
检查,也会遇到问题,因为在阅读chdir
的过程中,进行$dir
也会引起问题。内容,因此将在错误的位置查看以后的$dir/$subdir
实例。
答案 1 :(得分:2)
执行这样的逻辑而不更改目录要容易得多,但是如果您使用File::chdir或File::pushd,则在退出该范围时可以返回上一个目录。但是,通过使用诸如Path::Iterator::Rule这样的递归迭代器来处理子目录逻辑,可以轻松解决此问题:
use strict;
use warnings;
use Path::Iterator::Rule;
use Path::Tiny;
my $rule = Path::Iterator::Rule->new->not_directory;
foreach my $dir (@ARGV) {
my $fh = path("FileSize_$dir.txt")->openw;
my $next = $rule->iter($dir);
while (defined(my $item = $next->())) {
my $size = -s $item;
print $fh "$item $size\n";
}
}
或者,您可以使用visitor
回调,该回调将传递每个项目的完整路径(用于文件操作)和基本名称:
my $rule = Path::Iterator::Rule->new->not_directory;
foreach my $dir (@ARGV) {
my $fh = path("FileSize_$dir.txt")->openw;
$rule->all($dir, {visitor => sub {
my ($path, $basename) = @_;
my $size = -s $path;
print $fh "$basename $size\n";
}});
}