2016-04-01 51 views
0

我有在它的多個子目錄的目錄和每個子目錄有一個固定的文件集 - 每個類別一樣 -的Perl - 連接具有類似名稱的病毒碼文件和寫連結文件名列表

1)Main_dir 
1.1) Subdir1 with files 

- Test.1.age.txt 
- Test.1.name.txt 
- Test.1.place.csv 
.......... 
1.2) Subdir2 with files 
- Test.2.age.txt 
- Test.2.name.txt 
- Test.2.place.csv 
......... 

有大約20個文件夾,其中有10個文件。我需要首先將每個類別下的文件(如Test.1.age.txt和Test.2.age.txt)連接成一個combined.age.txt文件,一旦我完成所有連接,我想將這些文件名打印到新的Final_list中。 txt文件一樣

./Main_dir/Combined.age.txt 
./Main_dir/Combined.name.txt 

我能夠讀取陣列中的所有子目錄中的所有文件,但我不知道該怎麼辦了類似的文件名模式搜索。此外,將能夠找出代碼的打印輸出部分。任何人都可以請分享如何做這種模式搜索連接?到目前爲止我的代碼:

use warnings; 
use strict; 
use File::Spec; 
use Data::Dumper; 
use File::Basename; 

foreach my $file (@files) { 
print "$file\n"; 
} 
my $testdir = './Main_dir'; 
my @Comp_list = glob("$testdir/test_dir*/*.txt"); 

我試圖做的@Comp_list數組內容,我肯定需要學習模式搜索 -

foreach my $f1 (@Comp_list) { 
     if($f1 !~ /^(\./\.txt$/) { 
     print $f1; # check if reading the file right 


#push it to a file using concatfile( 
}} 

非常感謝!

+0

你似乎希望各地顛簸,你會浮動。你現在有幾個答案;請看看[*當有人回答我的問題時,我應該怎麼做?](http:// stackoverflow。com/help/someone-answers) – Borodin

+0

你好@Borodin!抱歉,對於您和rcedillo發佈的答案,花粉警報週末太糟糕了!我剛剛在我的數據上運行了腳本,我想發佈是否遇到任何問題。謝謝! – AnkP

回答

2

這應該爲你工作。我只是在表面上進行了測試,因爲它需要我花一些時間才能創建一些測試數據,因此,如果您手邊有一些信息,我希望您能夠回報任何問題

程序將找到的所有文件相當於您撥打glob,並根據其類型將它們放入存儲桶中。我已經假定名稱爲,正如你所示的那樣,它正好是,所以當文件名被分成點時,類型是倒數第二個字段;即Test.1.age.txt的類型是age

收集完所有的文件列表後,我使用了一種最初設計用來讀取命令行中指定的所有文件的技術。如果@ARGV設置爲文件的列表那麼<ARGV>操作就能把所有的文件中讀取,就好像它們是一個,所以很容易被複制到一個新的輸出文件

如果您需要在一個特定的順序連接起來的文件那麼我將不得不修改我的解決方案。目前,他們將在glob返回它們的順序進行處理 - 可能在它們的文件名的詞彙順序,但你不應該依賴於

use strict; 
use warnings 'all'; 
use v5.14.0; # For autoflush method 

use File::Spec::Functions 'catfile'; 

use constant ROOT_DIR => './Main_dir'; 

my %files; 

my $pattern = catfile(ROOT_DIR, 'test_dir*', '*.txt'); 

for my $file (glob $pattern) { 
    my @fields = split /\./, $file; 
    my $type = lc $fields[-2]; 
    push @{ $files{$type} }, $file; 
} 

STDOUT->autoflush; # Get prompt reports of progress 

for my $type (keys %files) { 

    my $outfile = catfile(ROOT_DIR, "Combined.$type.txt"); 
    open my $out_fh, '>', $outfile or die qq{Unable to open "$outfile" for output: $!}; 

    my $files = $files{$type}; 

    printf qq{Writing aggregate file "%s" from %d input file%s ... }, 
      $outfile, 
      scalar @$files, 
      @$files == 1 ? '' : 's'; 

    local @ARGV = @$files; 
    print $out_fh $_ while <ARGV>; 

    print "complete\n"; 
} 
+0

'STDOUT-> autoflush'是否需要模塊? (當然,很好的回答) – zdim

+0

@zdim:'autoflush'來自['IO :: Handle'](https://metacpan.org/pod/IO::Handle)。它的子類['IO :: File'](https://metacpan.org/pod/IO::File)[按需自動加載](http://search.cpan.org/dist/perl-5.14.0 /pod/perldelta.pod#Filehandle_method_calls_load_IO::File_on_demand)如果您使用Perl v5.14.0或更高版本 – Borodin

+0

哦......非常感謝您!不知道。 (我們在這裏運行v5.10 :(。 – zdim

2

我認爲如果您先對文件進行分類,那麼您可以使用它們更容易。

use warnings; 
use strict; 

use File::Spec; 
use Data::Dumper; 
use File::Basename; 

my %hash =(); 

my $testdir = './main_dir'; 
my @comp_list = glob("$testdir/**/*.txt"); 

foreach my $file (@comp_list){ 
    $file =~ /(\w+\.\d\..+\.txt)/; 
    next if not defined $1; 
    my @tmp = split(/\./, $1); 
    if (not defined $hash{$tmp[-2]}) { 
     $hash{$tmp[-2]} = [$file]; 
    }else{ 
     push($hash{$tmp[-2]}, $file); 
    } 
} 

print Dumper(\%hash); 

文件:

main_dir 
├── sub1 
│   ├── File.1.age.txt 
│   └── File.1.name.txt 
└── sub2 
    ├── File.2.age.txt 
    └── File.2.name.txt 

結果:

$VAR1 = { 
      'age' => [ 
        './main_dir/sub1/File.1.age.txt', 
        './main_dir/sub2/File.2.age.txt' 
        ], 
      'name' => [ 
         './main_dir/sub1/File.1.name.txt', 
         './main_dir/sub2/File.2.name.txt' 
        ] 
     }; 

您可以創建一個循環來連接和合並文件

+0

*「你可以創建一個循環來連接和合並文件」*我認爲這是OP有問題的部分! – Borodin

+0

嗨鮑羅丁,他寫道「但我不知道如何做類似文件名稱的模式搜索」。這就是爲什麼我只寫代碼來按類型對文件進行分組,在這一點上,我更容易編寫一個循環來進行連接。無論如何,很好的答案 – rcedillo

+0

是的,但也有一個循環'foreach我的$文件(@文件){...}'似乎什麼都不做,只是因爲@文件不存在而強制崩潰。當他們說他們患有癌症時,你不能只將所有人都送到腫瘤科醫生處。做一些診斷! – Borodin

相關問題