如何使用perl为主文件夹下的每个子文件夹创建一个新的输出文件?

时间:2014-12-18 19:37:09

标签: perl

我在主文件夹中有100个子文件夹。他们有不同的名字。每个子文件夹都包含一个.txt文件,该文件有10列。我想为每个子文件夹获取一个新的.txt文件。每个新的.txt文件都必须位于自己的文件夹中。那就是我在每个子文件夹中都会有2个.txt文件(旧的和新的)。我正在尝试选择起始线#34; ATOM"以及每个.txt文件中的一些列2,6,7和8。我的代码如下。它没有正常工作。它不会创建新的.txt文件。我怎么能弄清楚这个问题呢?

#!/usr/bin/perl

$search_text = "ATOM";
@files = <*/*.txt>;
foreach $file (@files) {
    print $file . "\n";

    open(DATA, $file);      
    open(OUT_FILE, ">$file a.txt");

    while ($line = <DATA>)
    {
        @fields = split /\s+/, $line;
        if ($line =~ m/$search_text/)
        { 

            print OUT_FILE "$fields[2]\t$fields[6]\t$fields[7]\t$fields[8]\n"; 
        }

    }

}
close(OUT_FILE);

1 个答案:

答案 0 :(得分:1)

要将输出文件a.txt放入与输入文件相同的目录中,您需要从输入文件名中提取目录名,并将其添加到输出文件名(a.txt)之前。有几种方法可以做到这一点;最简单的方法是使用标准模块File::Basename中的dirname()

use File::Basename;
my $dir = dirname($file);
open(OUT_FILE, ">", "$dir/a.txt") or die "Failed to open $dir/a.txt: $!";

或者您可以直接使用File::Spec

use File::Spec;
my ($volume, $dir) = File::Spec->splitpath($file);
my $outname = File::Spec->catpath($volume, $dir, 'a.txt');
open(OUT_FILE, ">", $outname) or die "Failed to open $outname: $!";

或者你可以使用regexp substitution

my $outname = ( $file =~ s![^/]+$!a.txt!r );
open(OUT_FILE, ">", $outname) or die "Failed to open $outname: $!";

Ps。无论如何,我建议采用一些有助于编写更好的Perl脚本的好习惯:

  1. 始终使用use strict;use warnings;启动您的脚本。修复他们产生的任何错误和警告。特别是,使用my声明所有局部变量,使它们具有词汇范围。

  2. 检查open()等函数的返回值,如果失败则中止脚本。 (我在上面的例子中做过这个。)

  3. 使用open()的三参数形式,正如我在上面的示例中所做的那样。如果你的文件名包含有趣的字符,那么破解的可能性要小得多。

  4. 考虑使用词法范围的文件句柄(open my $out_file, ...)而不是全局文件句柄(open OUT_FILE, ...)。我在上面的代码片段中没有这样做,因为我想让它们与你的其余代码保持兼容,但这是一个很好的做法。

  5. 如果您预先声明正则表达式,例如$search_text,请使用qr//而不是普通字符串,如下所示:

    my $search_text = qr/ATOM/;
    

    效率稍高,特殊字符的引用规则更加明智。

  6. 要从数组中打印多个列,请考虑使用join()和列表切片,如:

    print OUT_FILE join("\t", @fields[2,6,7,8]), "\n";
    
  7. 最后,如果我是你,我会重新考虑我的文件命名方案:输出文件名a.txt与您输入的文件名glob *.txt匹配,因此如果您运行它,您的脚本可能会中断连续两次。