#! perl -slw use strict; our $N ||= 1e3; our $PRE ||= '12'; my $base = 'c:/test/700432/'; sub incPath { my @path = unpack 'C*', $_[ 0 ]; my $full = $base; mkdir $full .= $_ . '/' for @path[ 0 .. $#path -1 ]; $full .= $path[ -1 ] . '.count'; if( -e $full ) { open my $fh, '+<', $full or die "$! : $full"; my $count = <$fh>; seek $fh, 0, 0; print $fh ++$count; close $fh; } else { open my $fh, '>', $full or die "$! : $full"; print $fh 1; close $fh; } } sub traversePrefix { my( $path, $code ) = @_; my @path = unpack 'C*', $path; my $prefix = $base . join '/', @path; return unless -e $prefix; my @dirs = $prefix; for my $dir ( @dirs ) { for my $file ( glob $dir . '*' ) { push( @dirs, $file . '/' ), next if -d $file; open my $fh, '<', $file or die "$! : $file"; chomp( my $count = scalar <$fh> ); ( $file ) = $file =~ m[^$base(.+).count$]; my $key = pack 'C*', split '/', $file; $code->( $key, $count ); } } } sub rndStr{ join'', @_[ map{ rand @_ } 1 .. shift ] } ## Generate $N keys (paths) and incr their counts for ( 1 .. $N ) { printf "\r$_\t"; my $key = rndStr 1+int( rand 5 ), map chr, 0..255; incPath( $key ); } ## Traverse starting from $PRE and print out the keys and counts traversePrefix $PRE, sub { print "@_"; };