0

我一直试图让我的 Perl 程序一次对 PDB 数据库一个文件进行排序。我需要的是一个读取文件的程序,进行一些模式匹配,并根据结果将文件移动到适当的文件夹而不更改文件名。到目前为止,我想出了这个:

#!/usr/bin/perl
use File::Basename;

@files = <top8000/rands/*> ; 
$file = 0;
$count = 1; 
while ( open (FILE, $files[$file]) )
{
    while (  $FILEREAD = <FILE> ) 
    {
        if ( $FILEREAD =~ "pattern" ) 
        {
            $count++;        
        };
    };
    $string ="$files[$file]";
    $filename = fileparse($string);
    if ($count >=2 ) {
        rename ( $files[$file] , "top8000/randsort/$filename.txt" );
    };
    $count = 1;
    $file++;
};

我知道我应该my在这里使用$stringand$filename变量,但是我的程序不能使用它运行,而且我真的不明白它的作用。除此之外,我无法弄清楚我的程序出了什么问题。将不胜感激任何帮助。

4

1 回答 1

1

好吧,你似乎把事情复杂化了。我猜你现在的问题是你正在尝试重命名一个仍然打开以供阅读的文件。作为一般规则,您应该始终检查所有文件交互的返回值,如下所示:

open my $fh, "<", $file or die "Cannot open file: $!";
rename $old, $new or die "Cannot rename: $!";

因为一般来说,此类错误通常应该被认为是致命的。

通过使用一些内置功能,您的程序可以大大简化:

use strict;
use warnings;  # always use these two
use File::Copy qw(move);

@ARGV = <top8000/rands/*.txt> unless @ARGV;  # default args    
my $outdir = "top8000/randsort";

while (<>) {           # read through the files
    if (/pattern/) {   # check each line
        close ARGV;    # close the file handle
        move $ARGV, $outdir or die "Cannot move $ARGV: $!";
    }
}

可以看到,使用模块时不需要指定文件名File::Copy:如果目标地址是文件夹,则使用旧名称。

我们正在使用菱形操作符<>,它在使用时使用标准输入 STDIN 文件句柄,或者——在我们的例子中——打开并读取作为脚本参数提供的文件@ARGV。因为这是 Perl,所以我们可以做我们想做的事,如果没有默认参数,只需输入默认参数即可。

因为您的计数检查了 1 个或多个命中,这实际上与在第一个匹配时移动文件相同,所以为什么不这样做呢?只要确保你先关闭文件!在这种情况下,文件句柄是ARGV. 这也跳到了 中的下一个文件@ARGV,这对我们来说非常方便。文件名包含在 中$ARGV,我们不需要进一步操作它,因此我们不再需要File::Basename模块。

File::Copy是 Perl 5 中的核心模块,因此无需安装。

于 2013-06-11T10:52:00.707 回答