我一直在尝试让我的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
和$string
变量之前使用$filename
,但是我的程序没有运行它,我真的不明白什么它确实。除此之外,我无法弄清楚我的程序有什么问题。非常感谢任何帮助。
答案 0 :(得分: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文件句柄,或者 - 在我们的例子中 - 打开并读取作为{{1}中脚本的参数给出的文件}。因为这是Perl,我们可以做我们想做的事情,如果没有,就放入默认参数。
因为您的计数检查了一次或多次点击,这实际上与在第一次匹配时移动文件相同,那么为什么不这样做呢?只需确保先关闭文件!在这种情况下,文件句柄是@ARGV
。这也会跳到ARGV
中的下一个文件,这对我们来说非常方便。文件名包含在@ARGV
中,我们无需进一步操作,因此我们不再需要$ARGV
模块。
File::Basename
是Perl 5中的核心模块,因此无需安装。