perl脚本无法读取其他目录中的文件

时间:2013-06-01 09:50:25

标签: perl

我正在编写一个只读取文件的脚本。我遇到的一个问题是,如果我传入路径(使用Getoptions :: Long),它会告诉我文件或目录不存在,即使它可以打印我的文件名。例如:

   thomaswtsang @ alfred:perl $ perl~ / Dropbox / dev / test-monkey / perl / fileReader.pl --path~ / Dropbox / dev / test-monkey / diff

     

没有这样的文件或目录:f1.txt at /Users/thomaswtsang/Dropbox/dev/test-monkey/perl/fileReader.pl第67行。

然后......转到该目录......

   thomaswtsang @ alfred:diff $ perl~ / Dropbox / dev / test-monkey / perl / fileReader.pl --path~ / Dropbox / dev / test-monkey / diff

     

(1/3)阅读f1.txt ...

     

(2/3)阅读f2.txt ...

     

阅读21 B

     

完整!

我真的不明白为什么我会这样做。权限问题?

my $path = shift;
my $run_in_fg = shift;
if (length($path) == 0){
    if ($run_in_fg){print "Using current directory...\n";}
    $path = cwd();
}
print $path . "\n";
opendir my $dir, $path or die "Cannot open directory: $!";
my @files = readdir $dir;
my $num_files = $#files;
my $i = 1;
my $total_size = 0;
$SIG{'INT'} = sub {print "\n";print_read_size($total_size); exit 1;};

foreach my $file (@files){
    if ($file =~ m/^\.+$/){next;}
    $file =~ s/[\r\n]+$//;
    open FILE, "<", $file or die "$!:$file";
    if ($run_in_fg){ print "($i/$num_files)Reading $file...\n";}
    while (my $line = <FILE>){
        #don't need to actually print to screen, just load to memory
    }
    $total_size += -s $file;
    close FILE or die $!;
    $i++;
}

print_read_size($total_size);
print "Complete!\n";

如果有更好的方法,请指出,谢谢!

2 个答案:

答案 0 :(得分:8)

 open FILE, "<", $file or die "$!:$file";

此行尝试在当前目录中打开$file。具体来说,readdir返回文件名,而不是路径。因此,必须在前面添加正确的路径:

  my $filepath = "$path/$file";
  open FILE, "<", $filepath or die "$!:$filepath";

关于风格的评论:

my $i = 1;
for my $file (@files){
  ...;
  $i++;
}

更好地表达为

for my $i (1 .. @files) {
   my $file = $files[$i - 1];
   ...;
}

而且if - 没有else只包含一个表达式的条件可以从

更改
if (COND) {EXPR}

EXPR if COND;

我觉得更容易阅读。

接下来,readdir不会在文件名后附加换行符。因此,从文件名末尾删除换行符是不必要的,错误 - 这些可能是某些文件系统(1)中文件名的合法字符。所以

$file =~ s/[\r\n]+$//;

是一个不必要的错误。

1:示例包括Ext2-Ext4系列(除/\0之外的所有字符),HFS(除:以外的所有字符),Posix模式下的NTFS(全部除了/\0)之外,Win32模式下的NTFS还禁止\*?:"<>|

在perl5,v10及更高版本中,

print SOMETHING, "\n";

可以表示为

use feature 'say'; # or use VERSION where VERSION >= 5.10

say SOMETHING;

打开文件时,最好使用词法变量作为文件句柄:

open my $fh, "<", $filepath or die "$!:$filepath";
while(my $line = <$fh>) {
  ...;
}

当引用计数降至零时,词法文件句柄会自动关闭。但是,明确关闭可能更适合更好的诊断。

答案 1 :(得分:1)

您需要在$path前加上readdir的文件名前缀,例如

 my @files = grep { ! -d $_ } map { "$path/$_" } readdir $dir;

上面使用$path为所有目录条目添加前缀,并从结果中删除所有目录(因为您不想打开它们)。