我有一个包含多个子目录的目录,每个子目录都有一组固定的文件 - 每个类别对应一个 -
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 :(得分: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'
]
};
您可以创建一个循环来连接和组合文件
答案 1 :(得分: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";
}