【问题标题】:Run a script in multiple directories with multiple output files in Perl (problems comparing hash key values)在 Perl 中使用多个输出文件在多个目录中运行脚本(比较哈希键值的问题)
【发布时间】:2018-01-15 08:28:24
【问题描述】:

我有一个看起来像这样的脚本,我想用它来搜索我所在的当前目录,打开该目录中的所有目录,打开与某些 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 内存的某种限制。任何帮助表示赞赏!

【问题讨论】:

  • push my @AbsDirs, ...; 没有意义,因为my @AbsDirs 创建了一个新变量。它应该只是push @AbsDirs, ...;
  • $AbsDirs[$a].$files[$b] 应该是"$AbsDirs[$a]/$files[$b]"
  • 提示:不要使用全局变量。将open INPUT1, ... 替换为open my $INPUT1, ...
  • 这个完整的脚本可以编译。它是实际的脚本,而不是以前的简化脚本,但也是如此。我得到空的输出文件!

标签: perl memory hashtable subdirectory


【解决方案1】:

原来我的问题在于我声明哈希的位置。出于某种原因,即使我只在它找到第一个输入文件后才声明它。除非我在 foreach 循环之前声明哈希,否则脚本将失败,该循环遍历 @AbsFiles 中的所有项目以搜索第一个输入文件,这很好,因为这意味着哈希在每个新目录中都被清除。但我不明白为什么它会失败,因为它应该只在找到输入文件名时声明(或清除)哈希。我想我不需要知道为什么它以前不起作用,但是一些帮助理解会很好。

我必须感谢其他用户帮助我实现这一点。他们试图回答我的问题但没有回答,然后在对该答案的评论中提示我在哪里声明我的哈希值。这个答案现在已被删除,所以我不能相信那个用户将我指向这个方向。我很想知道他们对 Perl 的理解,而我并没有让他们清楚这是问题所在。很抱歉我正忙于数据分析和会议,因此无法尽快回复该评论。

【讨论】:

    猜你喜欢
    • 2014-02-05
    • 1970-01-01
    • 1970-01-01
    • 2012-02-01
    • 1970-01-01
    • 2019-01-04
    • 1970-01-01
    • 2011-09-12
    • 1970-01-01
    相关资源
    最近更新 更多