使用PERL获取子目录中所有文件的名称和大小
我编写了一个例程来读取包含在两个文件夹及其所有子文件夹中的所有文件的名称和大小。根文件夹名称在命令行参数中提供,每个文件夹在for循环中处理,详细信息输出到两个文件夹各自的单独文件中。但我发现只有两个根文件夹中的文件名/大小被输出,我无法更改为子文件夹并重复该过程,因此子目录中的文件被忽略。调试跟踪显示chdir命令从未执行过,因此我的计算有问题,但我看不出它是什么。 代码如下所示使用PERL获取子目录中所有文件的名称和大小,perl,Perl,我编写了一个例程来读取包含在两个文件夹及其所有子文件夹中的所有文件的名称和大小。根文件夹名称在命令行参数中提供,每个文件夹在for循环中处理,详细信息输出到两个文件夹各自的单独文件中。但我发现只有两个根文件夹中的文件名/大小被输出,我无法更改为子文件夹并重复该过程,因此子目录中的文件被忽略。调试跟踪显示chdir命令从未执行过,因此我的计算有问题,但我看不出它是什么。 代码如下所示 #!/usr/bin/perl #!/usr/local/bin/perl use strict; use wa
#!/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;
#/usr/bin/perl
#!/usr/local/bin/perl
严格使用;
使用警告;
my$dir=$ARGV[0];
opendir(DIR,$DIR)或die“无法打开目录'$DIR'$!”;
my@subdirs=readdir(DIR)或die“无法读取目录'$DIR':$!”;
对于(我的$loopcount=1;$loopcount<3;$loopcount=$loopcount+1){
my$filename='FileSize.'$dir..txt';
打开(my$fh,“>”,$filename)或死亡“无法打开文件“$filename”$!”;
对于我的$subdir(sort@subdirs){
除非(-d$subdir){
#忽略此内部循环中的子目录
#仅处理文件
#将文件名和文件大小打印到输出文件
打印“正在处理文件\n”;
my$size=-s“$dir/$subdir”;
打印$fh“$subdir”、“”、“$size\n”;
}
elsif(-s“$dir/$subdir”){
#我们在这里是因为条目是子文件夹而不是文件
#如果此子文件夹大小非零,即有文件,则
#更改到此目录并重复外部for循环
chdir$subdir;
打印“更改到目录$subdir\n”;
打印“处理$subdir\n中的文件”;
};
}
#我们现在已经处理了第一个文件夹中的所有文件及其所有子文件夹
#现在将第二个根目录分配给$dir变量并重复循环
打印“开始下一个目录\n”;
$dir=$ARGV[1];
opendir(DIR,$DIR)或die“无法打开目录'$DIR'$!”;
@subdirs=readdir(DIR)或die“无法读取目录'$DIR':$!”;;
}
出口0;
命令行调用为“perl FileComp.pl DiskImage DiskImage1”
但仅输出根DiskImage和DiskImage1文件夹中文件的文件名和文件大小,子文件夹中的所有文件都将被忽略。
要更改为“elseif”条件的代码从未满足,并且代码从未执行,因此存在错误。
提前谢谢你的建议。这张支票很可能总是错的,因为你看错了东西
unless (-d $subdir) {
$subdir
是$dir
中文件或目录的文件名,因此要访问它,您需要使用$dir/$subdir
的完整相对路径,就像您在这里所做的那样:
my $size = -s "$dir/$subdir";
<>你也会遇到问题,除非你修改了<代码>,除非<代码> Chdir < /代码>也会造成问题,因为你正在做这件事,而在阅读“代码> $DIR <代码>的内容中,这样会在错误的地方看到后面的代码< > $dir/$didir 。因为你看错了东西
unless (-d $subdir) {
$subdir
是$dir
中文件或目录的文件名,因此要访问它,您需要使用$dir/$subdir
的完整相对路径,就像您在这里所做的那样:
my $size = -s "$dir/$subdir";
<>你也会遇到问题,除非你修改了<代码>,除非<代码> Chdir < /代码>也会造成问题,因为你正在做这件事,而在阅读“代码> $DIR <代码>的内容中,这样会在错误的地方看到后面的代码< > $dir/$didir 。更改目录,但如果确实使用或,则在退出该作用域时返回到上一个目录。但是,使用递归迭代器(如处理子目录逻辑的迭代器)更容易解决此问题:
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";
}});
}
在不更改目录的情况下执行这样的逻辑要容易得多,但是如果确实使用或,则在退出该作用域时返回到上一个目录。但是,使用递归迭代器(如处理子目录逻辑的迭代器)更容易解决此问题:
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";
}});
}
这将非常有用。这将是非常有用的。嗨,格林茨-非常感谢你的帮助-在我从CSPAN安装了Path::Iterator::Rule模块之后,这一切就成功了!!是的,一些模块有这样的迭代器,它们有时非常方便,这正是您想要的。值得注意的是,我有点吃惊地发现
File::pushd
并不(似乎)干净地支持简单的chdir
返回;如果我想回到同一个范围怎么办?可以undef
it,但为什么没有方法呢?如果不是这样的话,那么我希望能够保持pushd
-ing,然后使用我的堆栈chdir
到达我曾经去过的地方;某种类型的popd
。我看不出它会夺走简单性。只是一个注释,它是一个很好的功能,这就是pushd在shell中的工作方式,但是File::pushd决定利用Perl的动态作用域。从逻辑上讲,我认为如果它试图同时提供一个范围保护和一个显式的pushd/popd堆栈,那么它会变得混乱。您可以通过在顶层创建@dirs数组并执行push@dirs,pushd$foo代码>然后pop@dirs
作为popd,因此对象由该数组inst保存