use strict; use warnings; my %info; while () { chomp; my ($name,$fruit, $path) = split ' ',$_,3; # allow space in path name(s) $info{$name}{$fruit}=$path; } foreach my $name (sort keys %info) { print "$name\n"; foreach my $fruit (sort keys %{$info{$name}} ) { print " $fruit \t$info{$name}{$fruit}\n"; } } =PRINTS: Albert apple /path/to/somewhere/a Dex jackfruit /path/to/some where/d Jack apple /path/to/somewhere/c pineapple /path/to/some where/b =cut __DATA__ Albert apple /path/to/somewhere/a Jack pineapple /path/to/some where/b Jack apple /path/to/somewhere/c Dex jackfruit /path/to/some where/d