如何通过Perl处理多个目录中的文件名?

时间:2019-07-08 10:36:26

标签: perl

我正在使用Perl从不同的多个目录中逐步复制多个.txt文件。

我有以下文件夹:A_1A_2A_3,...
A_1文件夹中的文件列表为:
V_3_C_1.txtV_3_C_2.txt,...,V_3_C_38.txt
V_1_C_1.txtV_1_C_2.txt,...,V_1_C_38.txt。 由于某些原因,A_1文件夹中的文件可以分为V_3V_1

A_2文件夹中的文件列表为:
V_4_C_1.txtV_4_C_2.txt,...,V_4_C_38.txt
V_1_C_1.txtV_1_C_2.txt,...,V_1_C_38.txt
 A_2文件夹中的文件可以分为V_4V_1

我要运行Perl的系统(java程序)。我要提取文件名部分的第一件事。 我的代码在这里:

my % seen;
my @dups;
my @unqie;

my $file_list = '/home/V/Documents/A_1';
opendir (DIR, $file_list) or die "Could not open $file_list\n";  
my @vcf_files = grep (/\.txt$/, readdir DIR);  

for my $line (@vcf_files) {
    my @vcf_index = split ('_' , $line);
    my @dups = grep ++$seen{$_} ==2, $vcf_index[1]; #get the unique values, for example in `A_1` folder, I try to extract 3 and 1 from `V_3` and `V_1  `  
    push @unqie, @dups; #push into array for next steps. 

    for (my $i=1; $i <=38; $i++) {
        my @external_command = (
            "java",
            "-jar",
            "/home/V/Documents/beagle.03Jul19.b33.jar",
            "gt=/home/V/Documents/A_1/V_".$unqie[0]."_C_".$i."\.txt",
            "out = .............."
        );
        my @external_command_1 = (
            "java",
            "-jar",
            "/home/V/Documents/beagle.03Jul19.b33.jar",
            "gt=/home/V/Documents/A_1/V_".$unqie[1]."_C_".$i."\.txt",  
            "out = .............. "
        );

        my $out = system(@external_command);
        my $out_1 = system(@external_command_1);
        # ....
    }
}

对于此代码,java程序运行良好。 但是,当我为该代码添加循环时,我想一个一个地处理一个文件夹:打开A_1然后运行Java,完成。打开A_2,然后运行Java,完成...打开A_3,........

for (my $j=1; $j<=2; $j++) {
    my $file_list = '/home/v/Documents/A_' . $j;
    opendir (DIR, $file_list) or die "Could not open $file_list\n";

    my @vcf_files = grep (/\.txt$/, readdir DIR);
    for my $line (@vcf_files) {
        my @vcf_index = split ('_' , $line);
        my @dups = grep ++$seen{$_} ==2, $vcf_index[1];
        push @unqie, @dups;

        for (my $i=1; $i <=38; $i++) {
            my @external_command = (
                "java",
                "-jar",
                "/home/V/Documents/beagle.03Jul19.b33.jar",
                "gt=/home/V/Documents/A_.$j/V_" . $unqie[0] . "_C_".$i."\.txt",  
                "out = .............."
            );
            my @external_command_1 = (
                "java",
                "-jar",
                "/home/victor/Documents/beagle.03Jul19.b33.jar",
                "gt=/home/V/Documents/A_.$j/V_".$unqie[1]."_C_".$i."\.txt",  
                "out = .............."
            );

            my $out = system(@external_command);
            my $out_1 = system(@external_command_1);
        }
    }
}

我无法获得想要的结果。我正在使用打印检查。我想我在文件名部分知道一些错误,但是我无法解决。

有人可以帮我弄清楚吗?谢谢

1 个答案:

答案 0 :(得分:2)

一种调试此类内容的好方法是不运行程序,而是打印命令行以查看将要运行的内容。

也就是说,替换这些行:

my $out = system(@external_command);
my $out_1 = system(@external_command_1);

带有这些:

print "@external_command\n";
print "@external_command_1\n";

(顺便说一句,您的原始代码似乎有误解-system()返回流程退出代码,而不是输出。)

运行该代码,您的第一个代码给我这样的输出:

java -jar /home/V/Documents/beagle.03Jul19.b33.jar gt=/home/V/Documents/A_1/V__C_1.txt out = ..............
java -jar /home/V/Documents/beagle.03Jul19.b33.jar gt=/home/V/Documents/A_1/V__C_1.txt out = ..............
java -jar /home/V/Documents/beagle.03Jul19.b33.jar gt=/home/V/Documents/A_1/V__C_2.txt out = ..............
java -jar /home/V/Documents/beagle.03Jul19.b33.jar gt=/home/V/Documents/A_1/V__C_2.txt out = ..............

这对我来说似乎不对。看到您有类似V__C_1.txt的信息。看起来好像缺少两个下划线之间的值。它来自以下代码:

"gt=/home/V/Documents/A_.$j/V_".$unqie[0]."_C_".$i."\.txt"

这段代码:

"gt=/home/V/Documents/A_.$j/V_".$unqie[1]."_C_".$i."\.txt"

因此,看来@unqie从未获得任何数据。这意味着@dup也从不获取任何数据。

运行第二个程序将得到如下输出:

java -jar /home/V/Documents/beagle.03Jul19.b33.jar gt=/home/V/Documents/A_.1/V__C_1.txt out = ..............
java -jar /home/victor/Documents/beagle.03Jul19.b33.jar gt=/home/V/Documents/A_.1/V__C_1.txt out = ..............

与第一个版本存在相同的问题(大概是由同一件事引起的),但是它也有-A_.1。来自以下代码:

"gt=/home/V/Documents/A_.$j/V_" . $unqie[0] . "_C_".$i."\.txt",

具体地说,来自A_.$j。我认为您是将点表示为串联运算符,但是由于它位于带引号的字符串中,因此只能将其解释为点。只需删除点即可轻松解决。

很难获得更多帮助,因为我不太清楚您要做什么,并且%seen@unqie之类的变量不加解释地存在。但是这里还有其他一些提示。

  • 添加use strictuse warnings。并解决他们将发现的问题。
  • for (my $j=1; $j<=2; $j++)可能更清楚地写为for my $i (1 .. 2)
  • 对目录句柄(opendir my $dir_h, $file_listreaddir $dir_h)使用词法变量
  • split的第一个参数是正则表达式(split /_/, $line
  • 变量被用双引号引起来的字符串

如果您尝试做的事情有所扩展,那么我们可能会获得更多帮助。