my %controlCentre=(); $controlCentre{ FH } = []; $controlCentre{ DH } = []; Traverse( tree => 'whatever-path', control => \%controlCentre ); sub Traverse{ my %par = (@_); my $dh = OpenDir(dir=>$par{ tree }, control=>$par{control}); foreach my $file ( grep !/^\./, readdir $dh ) { my $path = "$par{tree}/$file"; if ( -d $path ) { Traverse( tree => $path, control => $par{ control } ); else { ProcessFile( name => $path, control => $par{ control } ); } } CloseDir( dh => $dh, control => $par{ control }); } sub ProcessFile{ my %par =(@_); my $fh = Open( cmd => "<$par{name}", control =>$par{control} ); # ... # process <$fh> here with any recursive calls # to ProcessFile that may be required #... Close( control => $par{ control } ), fh=>$fh ); } sub Open{ my %par = (@_); open my $fh, $par{ cmd }; my $aref=$par{ control } -> { FH }; push @$aref, $fh; # N.B. $#$aref is now one less than # the count of open files return $fh; } sub Close{ my %par = (@_); close $par{ fh }; my $aref = $par{ control } -> { FH }; my $fh = pop @$aref; ( $fh eq $par{ fh } ) or die "fh stack was abused: " . "$fh does not match $par{ fh }"; } sub OpenDir{ my %par = (@_); opendir my $dh, $par{ dir }; my $aref=$par{ control } -> { DH }; push @$aref, $dh; return $dh; } sub CloseDir my %par = (@_); closedir $par{ dh }; my $aref = $par{ control } -> { DH }; my $dh = pop @$aref; ( $dh eq $par{ dh } ) or die "dh stack was abused: " . "$dh does not match $par{ dh }"; }