use strict; use warnings; use Data::Dumper; my %city_data = (); foreach my $filename ( 'cp_123456', 'cp_123457') { my ( $city, $id ) = split /_/, $filename; open THIS, "<$filename" or die "Can't open $filename for reading: $!"; chomp ( my @tmp = ); close THIS; push @{ $city_data{$city}{$id} }, @tmp; } print Dumper( \%city_data ); #### $VAR1 = { 'cp' => { '123456' => [ 'this is some data', 'this is a test' ], '123457' => [ 'this is the second file', 'this is another line', 'this is the third line' ] } };