2016-04-27 41 views
0

我对Perl完全陌生,我有一段代码让我回来一个空文件处理程序。为什么我的文件处理程序为空? PERL

my $md5dir = "...plib/test/md5sum"; #IN MY PROG, IS THE FULL PATH 
opendir(DIR, $md5dir) or die "Can't open directory $md5dir: $!"; 
my @md5files = grep !/^\.\.?$/, readdir(DIR); 
closedir(DIR); 

if ( scalar @md5files < 1 
    || scalar @md5files > 8 
    || (scalar @md5files % 2 != 0)) 
{ 
    print "Incorrect amount of files in directory. Aborting.\n"; 
    exit 1; 
} 
else { 
    for (my $i = 0; ($i < scalar @md5files/2); $i++) { 
     my $file1 = $md5files[$i]; 
     open(my $fh1, $file1) or die "Fail to open file $file1 $!"; 
     my $file2 = $md5files[ $i + 3 ]; 
     open(my $fh2, $file2) or die "Fail to open file $file2 $!"; 
     print "2.", $file1, " ", $file2, "\n"; 
     my $first1 = substr($file1, 0, 4); 
     my $first2 = substr($file2, 0, 4); 
     if (($first1 cmp $first2) == 0) { 
     if (eof $fh1) { print "No lines\n"; } 
     else    { my $line1 = <$fh1>; print "$line1\n"; } 
     if (eof $fh2) { print "No lines2\n"; } 
     else    { my $line2 = <$fh2>; print "$line2\n"; } 
     close $fh1; 
     close $fh2; 
     } 
    } # for 
} # else 

输出是这样的:

2.SAM5_27-04-2016_11:21:20.md5 SAM5_27-04-2016_11:20:11.md5 
No lines 
No lines2 
2.SAM6_27-04-2016_11:18:25.md5 SAM6_25-04-2016_10:38:38.md5 
No lines 
No lines2 
2.SAM4_27-04-2016_11:19:06.md5 SAM4_27-04-2016_11:17:22.md5 
No lines 
No lines2 

在目录中的md5sum:

:md5sum>ls -la 
total 16 
drwxrwxr-x 2 ateam ateam  4096 Apr 27 11:24 ./ 
drwxrwxr-x 4 ateam ateam  4096 Apr 27 11:24 ../ 
-rw-rw-r-- 1 ateam ateam   63 Apr 27 11:17 SAM4_27-04-2016_11:17:22.md5 
-rw-rw-r-- 1 ateam ateam   63 Apr 27 11:19 SAM4_27-04 2016_11:19:06.md5 
-rw-rw-r-- 1 ateam ateam   63 Apr 27 11:20 SAM5_27-04-2016_11:20:11.md5 
-rw-rw-r-- 1 ateam ateam   0 Apr 27 11:21 SAM5_27-04-2016_11:21:20.md5 
-rw-rw-r-- 1 ateam ateam   63 Apr 25 10:38 SAM6_25-04-2016_10:38:38.md5 
-rw-rw-r-- 1 ateam ateam   63 Apr 27 11:18 SAM6_27-04-2016_11:18:25.md5 

有人可以解释为什么filehandlers都上来了空?我验证了文件的打印。它们都在数组中打印得很好,并且文件处理程序正在打开......由于文件不是空的,还有什么可能是错误的? (以及所有除了一个...)

只是为了查看文件......以防万一。 打开第一个文件,我得到:

03c0cf2ab0da62832bfc6970d4505746 SAM4_27-04-2016_11:17:22.csv 

编辑::: 我做了一个小幅调整的文件:

if (($first1 cmp $first2) == 0) { 
      if (tell($fh1) == -1){ print "No lines\n";} 
      else {my $line1= <$fh1>; print "$line1\n"; } 
      if (eof $fh2){ print "No lines2\n";} 
      else { my $line2= <$fh2>; print "$line2\n"; } 
      close $fh1;      close $fh2; 
} 

,并得到这个输出,而不是:

2.SAM5_27-04-2016_11:21:20.md5 SAM5_27-04-2016_11:20:11.md5 
Use of uninitialized value in concatenation (.) or string at mulftptest line 53. 

No lines2 
2.SAM6_27-04-2016_11:18:25.md5 SAM6_25-04-2016_10:38:38.md5 
Use of uninitialized value in concatenation (.) or string at mulftptest line 53. 

No lines2 
2.SAM4_27-04-2016_11:19:06.md5 SAM4_27-04-2016_11:17:22.md5 
Use of uninitialized value in concatenation (.) or string at mulftptest line 53. 

No lines2 

本质,我知道这是告诉我,我试图使用“空”变量。但是,我不明白为什么它是空的。

+0

@eballes它默认为“<”,所以我不认为这就是问题所在。尽管为了可读性/可维护性,您应该始终指定它 –

+0

'<:编码(UTF-8)'这件事? –

+0

我试过了,它没有帮助。 –

回答

4

的主要问题是,readdir只返回文件名,不带任何路径信息

这意味着你在当前工作目录中打开SAM5_27-04-2016_11:21:20.md5,而不是在md5sum目录。通常你打开调用就失败了,但似乎你有你的脚本目录

的同名伪空文件。如果你写你的公开招募这样的,而不是那么它应该为你

open my $fh1, '<', "$md5dir/$file1" or die "Fail to open file $file1: $!"; 
工作

并且不要为此使用tell。无论文件是否为空,它在开始时都会返回零。你真的想要-s $fh1,它返回文件的大小以字节为单位,并可用于文件名或打开文件句柄

+0

只有在这种情况下才会在开始时告诉返回0?我认为告诉对于这种目的是有用的。 –

+0

有人告诉我,这是正确的。让我在今天早上进行验证,然后我会将这个答案接受。谢谢。 –

+0

@noc_coder:'tell'返回从文件中读取的字节数。打开文件后立即读取零字节,所以'tell'将返回零,无论有没有更多的东西要读 – Borodin

1

我最好的猜测是你需要这样的东西。我敢肯定,你必须包含MD5校验,并希望他们比较

我做了这个更直接以这些方式文件的目录

  • use autodie在程序的顶部。这是一个检查大多数Perl IO操作的编译指示,并且可以帮助您验证每个调用是否成功。它被引入到v5.10的核心perl中。1和可靠

  • 我添加了一个use constant为路径的MD5文件

  • 目录我用glob代替opendir/readdir找到在md5sum目录下,以.md5结尾的所有文件。 glob将永远不会返回伪目录...,但如果有人奇怪,总是有可能将xx.md5作为目录。您可能需要增加一个检查

有一个循环来构建一个涉及每一个“前缀”(前缀的第一个下划线之前是在文件名中的所有字符),以每个文件与前缀的散列

检查哈希以确保每个前缀的目录中都有文件。这似乎符合原始检查

现在有一个散列将每个前缀与两个文件关联起来,问题似乎已经解决。我的代码一起显示所有的前缀与它的两个文件的名称和MD5字符串,它们含有

use strict; 
use warnings 'all'; 
use autodie; 

use constant MD5_DIR => '...plib/test/md5sum'; #IN YOUR PROG, IS THE FULL PATH 
chdir MD5_DIR; 

my %files; 

# Build a hash of files collected by prefix 
# 
for my $file (glob '*.md5') { 
    next unless my ($prefix) = $file =~/^ ([^_]+) /x; 
    push @{ $files{$prefix} }, $file; 
} 


# Check that there are exactly two files with each prefix 
# 
{ 
    my $errors; 

    while (my ($prefix, $files) = each %files) { 

     my $n = @$files; 

     if (@$files != 2) { 
      warn qq{$n files fouhd for prefix "${prefix}_"\n}; 
      ++$errors; 
     } 
    } 

    die "Dying because errors found in source directory" if $errors; 
} 

# Display every pair of files by prefix 
# 
while (my ($prefix, $files) = each %files) { 

    my ($file1, $file2) = sort @$files; 

    print "Prefix: $prefix\n"; 

    for my $file (sort @$files) { 
     open my $fh, '<', $file; 
     my $md5 = <$fh>; 
     $md5 =~ s/\s+\z//; 
     print " File: $file\n"; 
     print "  MD5: $md5\n"; 
    } 
} 
相关问题