打开特定目录并读取所有文本文件

时间:2014-08-21 10:00:41

标签: perl cmd

以下代码进入文件夹($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将不会被硬编码。分享的任何解决方案或有用资源?谢谢!

4 个答案:

答案 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

进行增强

为了便于管理完整路径和文件信息,我建议使用像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; } }