以下代码进入文件夹($directory)
搜索文本文件并打印出filename and size
。如果CMD路径为c:\modules\STP\New
,它可以正常工作,它能够读取特定文件夹中的.txt
个文件。我猜它工作正常,因为它与$directory
相匹配。不幸的是,当我在c:\modules\STP
等不同路径上运行代码时,会显示错误。错误是Can't call method "size" on a undefined value at line 12
。我该如何解决这个问题?
my $directory = 'c:\modules\STP\New';
my $file='filename.txt';
my $OUTFILE;
open $OUTFILE, '>>', $file;
my @files = do {
opendir (my $dh, $directory);
grep {/^.*\.txt\z/si} readdir($dh);
};
foreach(@files){
my $filesize = stat($_)->size; #<<<< LINE 12
print { $OUTFILE } "$filesize $_" ,"\n";
}
预期结果:
我希望代码可以在c:\modules\STP
或任何其他CMD路径中运行。我这样做是因为我希望重用代码。很快,$directory
将不会被硬编码。分享的任何解决方案或有用资源?谢谢!
答案 0 :(得分:2)
使用已提供文件完整路径的glob()
,或使用map
添加路径,
my @files = do {
opendir (my $dh, $directory) or die $!;
map { "$directory/$_" }
grep { /^.*\.txt\z/si }
readdir($dh);
};
答案 1 :(得分:2)
在执行stat
等文件操作时,您只需要包含完整路径信息。
以下是您的脚本的清理:
use strict;
use warnings;
use autodie;
use File::stat;
my $directory = 'c:\modules\STP\New';
my $file = 'filename.txt';
open my $outfh, '>>', $file;
opendir my $dh, "$directory";
while (my $file = readdir $dh) {
next unless $file =~ /\.txt$/i;
my $filesize = stat("$directory\\$file")->size; # Include full path info
print $outfh "$filesize $file\n";
}
为了便于管理完整路径和文件信息,我建议使用像Path::Class
这样的模块。
以下内容与您的脚本完全相同,但确保您不会错过文件测试中的路径信息:
use strict;
use warnings;
use autodie;
use Path::Class;
my $dir = dir('c:\modules\STP\New');
open my $outfh, '>>', 'filename.txt';
while (my $file = $dir->next) {
next unless $file =~ /\.txt$/i;
printf $outfh "%s %s\n", $file->stat->size, $file->basename;
}
答案 2 :(得分:0)
您还可以使用一些CPAN模块,这些模块允许您使用许多额外的缓动功能,我最喜欢的是Path::Tiny。
来自文档:
此模块提供了一个用于处理文件的小型快速实用程序 路径。使用比File :: Spec更友好,并提供简单 从其他几个核心文件处理模块访问函数。 它的目标是比CPAN上的许多替代品更小更快 同时帮助人们以一致而少的方式做许多共同事 容易出错的方式。
您的代码使用Path :: Tiny
use 5.010;
use warnings;
use Path::Tiny;
my $directory = $ARGV[0] // "."; #use 1st argument or current dir as default
my $pattern = qr/\.txt$/i; #define your pattern to match
$iter = path($directory)->iterator({ recurse => 0 });
#change to 1, if want recursively search subdirs
while ( $path = $iter->() ) {
next unless $path =~ $pattern;
say "$path: ", $path->stat->size;
}
答案 3 :(得分:0)
#!/usr/bin/perl
use strict;
use warnings;
use File::Find;
my @content;
my $basedir = $ARGV[0];
if ( ! $basedir ){ $basedir = '/home/iwts/scripts'; }
find( \&wanted, $basedir );
foreach my $file ( @content ) {
my $cmd = `ls -lh $file | awk '{print \$9 "\t" \$5 }'`;
print $cmd;
}
sub wanted() { if ( $_ =~ m|^.*\.txt| ) { push @content, $File::Find::name; return; } }