in reply to Numeric summarisation from data in a hash?

The following code (or some derivation of it) should be what you want. Basically it goes through the hash once and builds an array-of-arrays to store the indexes of the files, broken down by duration. Then just iterates through that array to print out the results. :
#!/usr/bin/perl -w use strict; # maximal $ of minutes my $max_bucket=5; my %file; $file{1}{TITLE}='foo'; $file{1}{SIZE}='5'; $file{1}{VLENGTH}='0 days 0 hours 4 mins 5 secs'; $file{2}{TITLE}='bar'; $file{2}{SIZE}='92'; $file{2}{VLENGTH}='0 days 0 hours 4 mins 13 secs'; $file{3}{TITLE}='baz'; $file{3}{SIZE}='1'; $file{3}{VLENGTH}='0 days 0 hours 2 mins 23 secs'; # initialize stats array my @stat; for(my $c=0;$c<=$max_bucket;$c++){ $stat[$c]=[]; } # populate stats array my $k; foreach $k(keys %file){ my ($d,$h,$m)=$file{$k}{VLENGTH}=~/(\d+)\s*days\s*(\d+)\s*hours\s*(\ +d+)\s*mins/i; my $duration=$m+$h*60+$d*60*24; $duration=$max_bucket if($duration>$max_bucket); push @{$stat[$duration]},$k; } # iterate through stats array to print out counts for (my $c=0;$c<=$max_bucket;$c++){ print "there are ".(scalar @{$stat[$c]})." clips "; if($c==$max_bucket){ print "greater than $c mins :\n"; }else{ print "between $c and ".($c+1)." mins :\n"; } } # iterate through stats array to print out names for (my $c=0;$c<=$max_bucket;$c++){ print "Names of clips "; if($c==$max_bucket){ print "greater than $c mins : "; }else{ print "between $c and ".($c+1)." mins : "; } print "".(join ', ',map {$file{$_}{TITLE}} @{$stat[$c]})."\n"; }