use strict; use warnings; use Data::Dumper; my @paths = qw( This/is/the/full/path/file.abc.part-1.txt This/is/the/full/path/file.abc.part-2.txt This/is/the/full/path/file.abc.part-3.txt This/is/the/full/path/file.def.part-1.txt This/is/the/full/path/file.def.part-2.txt This/is/the/full/path/file.ghi.part-1.txt This/is/the/full/path/file.jkl.part-2.txt This/is/the/full/path/file.mno.part-5.txt ); my %combo; foreach my $pathfile ( @paths ) { if( $pathfile =~ m/^(.+file\.)(\w+?)\.(part-\d+)\.txt$/ ) { push( @{ $combo{$1}{$2} }, $3 ); } else { warn "$pathfile does not match expected format"; } } foreach my $path ( keys %combo ) { foreach my $type ( keys %{ $combo{$path} } ) { if( scalar @{ $combo{$path}{$type} } > 1 ) { my $newfile = join( '', $path, $type, '.MERGED.txt' ); print "These files go into $newfile:\n"; print ' ', join( ', ', @{ $combo{$path}{$type} } ), "\n"; } } } print Dumper( \%combo );