运行 多个目录中的脚本在 Perl 中具有多个输出文件(比较散列键值的问题)
Run a script in multiple directories with multiple output files in Perl (problems comparing hash key values)
我有一个看起来像这样的脚本,我想用它来搜索我所在的当前目录,打开该目录中的所有目录,打开所有匹配某些 RE 的文件(fastq 文件具有一种每四行放在一起的格式),对这些文件进行一些处理,并将一些结果写入每个目录中的一个文件。 (注意:实际脚本的作用远不止于此,但我认为我有一个与文件夹迭代相关的结构性问题,因为当在一个文件夹中使用简化版本时该脚本有效,所以我在这里发布了一个简化版本)
#!user/local/perl
#Created by C. Pells, M. R. Snyder, and N. T. Marshall 2017
#Script trims and merges high throughput sequencing reads from fastq files for a specific primer set
use Cwd;
use warnings;
my $StartTime= localtime;
my $MasterDir = getcwd; #obtains a full path to the current directory
opendir (DIR, $MasterDir);
my @objects = readdir (DIR);
closedir (DIR);
foreach (@objects){
print $_,"\n";
}
my @Dirs = ();
foreach my $O (0..$#objects){
my $CurrDir = "";
if ((length ($objects[$O]) < 7) && ($O>1)){ #Checking if the length of the object name is < 7 characters. All samples are 6 or less. removing the first two elements: "." and ".."
$CurrDir = $MasterDir."/".$objects[$O]; #appends directory name to full path
push (@Dirs, $CurrDir);
}
}
foreach (@Dirs){
print $_,"\n";#checks that all directories were read in
}
foreach my $S (0..$#Dirs){
my @files = ();
opendir (DIR, $Dirs[$S]) || die "cannot open $Dirs[$S]: $!";
@files = readdir DIR; #reads in all files in a directory
closedir DIR;
my @AbsFiles = ();
foreach my $F (0..$#files){
my $AbsFileName = $Dirs[$S]."/".$files[$F]; #appends file name to full path
push (@AbsFiles, $AbsFileName);
}
foreach my $AF (0..$#AbsFiles){
if ($AbsFiles[$AF] =~ /_R2_001\.fastq$/m){ #finds reverse fastq file
my @readbuffer=();
#read in reverse fastq
my %RSeqHash;
my $c = 0;
print "Reading, reversing, complimenting, and trimming reverse fastq file $AbsFiles[$AF]\n";
open (INPUT1, $AbsFiles[$AF]) || die "Can't open file: $!\n";
while (<INPUT1>){
chomp ($_);
push(@readbuffer, $_);
if (@readbuffer == 4) {
$rsn = substr($readbuffer[0], 0, 45); #trims reverse seq name
$cc++ % 10000 == 0 and print "$rsn\n";
$RSeqHash{$rsn} = $readbuffer[1];
@readbuffer = ();
}
}
}
}
foreach my $AFx (0..$#AbsFiles){
if ($AbsFiles[$AFx] =~ /_R1_001\.fastq$/m){ #finds forward fastq file
print "Reading forward fastq file $AbsFiles[$AFx]\n";
open (INPUT2, $AbsFiles[$AFx]) || die "Can't open file: $!\n";
my $OutMergeName = $Dirs[$S]."/"."Merged.fasta";
open (OUT, ">", "$OutMergeName");
my $cc=0;
my @readbuffer = ();
while (<INPUT2>){
chomp ($_);
push(@readbuffer, $_);
if (@readbuffer == 4) {
my $fsn = substr($readbuffer[0], 0, 45); #trims forward seq name
#$cc++ % 10000 == 0 and print "$fsn\n$readbuffer[1]\n";
if ( exists($RSeqHash{$fsn}) ){ #checks to see if forward seq name is present in reverse seq hash
print "$fsn was found in Reverse Seq Hash\n";
print OUT "$fsn\n$readbuffer[1]\n";
}
else {
$cc++ % 10000 == 0 and print "$fsn not found in Reverse Seq Hash\n";
}
@readbuffer = ();
}
}
close INPUT1;
close INPUT2;
close OUT;
}
}
}
my $EndTime= localtime;
print "Script began at\t$StartTime\nCompleted at\t$EndTime\n";
同样,我知道该脚本无需遍历文件夹即可运行。但是对于这个版本,我只得到空的输出文件。由于我在此脚本中插入的打印函数,我确定 Perl 无法在来自 INPUT2 的散列中找到变量 $fsn 作为键。我不明白为什么因为每个文件都在那里并且当我不遍历文件夹时它可以工作所以我知道键匹配。因此,要么我遗漏了一些简单的东西,要么这是我发现的对 Perl 内存的某种限制。感谢您的帮助!
原来我的问题出在我在哪里声明散列。出于某种原因,即使我只在找到第一个输入文件后才声明它。脚本失败,除非我在 foreach 循环之前声明散列,循环遍历 @AbsFiles 中的所有项目以搜索第一个输入文件,这很好,因为这意味着散列在每个新目录中被清除。但我不明白为什么它会像以前那样失败,因为它应该只在找到输入文件名时才声明(或清除)散列。我想我不需要知道为什么它以前不起作用,但一些帮助理解会很好。
我必须感谢另一位用户帮助我实现了这一点。他们试图回答我的问题但没有回答,然后给了我关于我在对该答案的评论中声明哈希的位置的提示。该答案现已删除,因此我不能相信该用户向我指出了这个方向。我很想知道他们对 Perl 有什么了解,而我不了解,这让他们清楚地知道这就是问题所在。很抱歉,我忙于数据分析和会议,所以我无法尽快回复该评论。
我有一个看起来像这样的脚本,我想用它来搜索我所在的当前目录,打开该目录中的所有目录,打开所有匹配某些 RE 的文件(fastq 文件具有一种每四行放在一起的格式),对这些文件进行一些处理,并将一些结果写入每个目录中的一个文件。 (注意:实际脚本的作用远不止于此,但我认为我有一个与文件夹迭代相关的结构性问题,因为当在一个文件夹中使用简化版本时该脚本有效,所以我在这里发布了一个简化版本)
#!user/local/perl
#Created by C. Pells, M. R. Snyder, and N. T. Marshall 2017
#Script trims and merges high throughput sequencing reads from fastq files for a specific primer set
use Cwd;
use warnings;
my $StartTime= localtime;
my $MasterDir = getcwd; #obtains a full path to the current directory
opendir (DIR, $MasterDir);
my @objects = readdir (DIR);
closedir (DIR);
foreach (@objects){
print $_,"\n";
}
my @Dirs = ();
foreach my $O (0..$#objects){
my $CurrDir = "";
if ((length ($objects[$O]) < 7) && ($O>1)){ #Checking if the length of the object name is < 7 characters. All samples are 6 or less. removing the first two elements: "." and ".."
$CurrDir = $MasterDir."/".$objects[$O]; #appends directory name to full path
push (@Dirs, $CurrDir);
}
}
foreach (@Dirs){
print $_,"\n";#checks that all directories were read in
}
foreach my $S (0..$#Dirs){
my @files = ();
opendir (DIR, $Dirs[$S]) || die "cannot open $Dirs[$S]: $!";
@files = readdir DIR; #reads in all files in a directory
closedir DIR;
my @AbsFiles = ();
foreach my $F (0..$#files){
my $AbsFileName = $Dirs[$S]."/".$files[$F]; #appends file name to full path
push (@AbsFiles, $AbsFileName);
}
foreach my $AF (0..$#AbsFiles){
if ($AbsFiles[$AF] =~ /_R2_001\.fastq$/m){ #finds reverse fastq file
my @readbuffer=();
#read in reverse fastq
my %RSeqHash;
my $c = 0;
print "Reading, reversing, complimenting, and trimming reverse fastq file $AbsFiles[$AF]\n";
open (INPUT1, $AbsFiles[$AF]) || die "Can't open file: $!\n";
while (<INPUT1>){
chomp ($_);
push(@readbuffer, $_);
if (@readbuffer == 4) {
$rsn = substr($readbuffer[0], 0, 45); #trims reverse seq name
$cc++ % 10000 == 0 and print "$rsn\n";
$RSeqHash{$rsn} = $readbuffer[1];
@readbuffer = ();
}
}
}
}
foreach my $AFx (0..$#AbsFiles){
if ($AbsFiles[$AFx] =~ /_R1_001\.fastq$/m){ #finds forward fastq file
print "Reading forward fastq file $AbsFiles[$AFx]\n";
open (INPUT2, $AbsFiles[$AFx]) || die "Can't open file: $!\n";
my $OutMergeName = $Dirs[$S]."/"."Merged.fasta";
open (OUT, ">", "$OutMergeName");
my $cc=0;
my @readbuffer = ();
while (<INPUT2>){
chomp ($_);
push(@readbuffer, $_);
if (@readbuffer == 4) {
my $fsn = substr($readbuffer[0], 0, 45); #trims forward seq name
#$cc++ % 10000 == 0 and print "$fsn\n$readbuffer[1]\n";
if ( exists($RSeqHash{$fsn}) ){ #checks to see if forward seq name is present in reverse seq hash
print "$fsn was found in Reverse Seq Hash\n";
print OUT "$fsn\n$readbuffer[1]\n";
}
else {
$cc++ % 10000 == 0 and print "$fsn not found in Reverse Seq Hash\n";
}
@readbuffer = ();
}
}
close INPUT1;
close INPUT2;
close OUT;
}
}
}
my $EndTime= localtime;
print "Script began at\t$StartTime\nCompleted at\t$EndTime\n";
同样,我知道该脚本无需遍历文件夹即可运行。但是对于这个版本,我只得到空的输出文件。由于我在此脚本中插入的打印函数,我确定 Perl 无法在来自 INPUT2 的散列中找到变量 $fsn 作为键。我不明白为什么因为每个文件都在那里并且当我不遍历文件夹时它可以工作所以我知道键匹配。因此,要么我遗漏了一些简单的东西,要么这是我发现的对 Perl 内存的某种限制。感谢您的帮助!
原来我的问题出在我在哪里声明散列。出于某种原因,即使我只在找到第一个输入文件后才声明它。脚本失败,除非我在 foreach 循环之前声明散列,循环遍历 @AbsFiles 中的所有项目以搜索第一个输入文件,这很好,因为这意味着散列在每个新目录中被清除。但我不明白为什么它会像以前那样失败,因为它应该只在找到输入文件名时才声明(或清除)散列。我想我不需要知道为什么它以前不起作用,但一些帮助理解会很好。
我必须感谢另一位用户帮助我实现了这一点。他们试图回答我的问题但没有回答,然后给了我关于我在对该答案的评论中声明哈希的位置的提示。该答案现已删除,因此我不能相信该用户向我指出了这个方向。我很想知道他们对 Perl 有什么了解,而我不了解,这让他们清楚地知道这就是问题所在。很抱歉,我忙于数据分析和会议,所以我无法尽快回复该评论。