#!/usr/bin/perl use strict; use Benchmark; use File::Find (); my @found; my $ext = ''; if ( @ARGV >= 2 and $ARGV[0] eq '-e' ) { shift; $ext = shift; } my @paths = ( @ARGV ) ? @ARGV : ( "." ); die "Usage: $0 [-e ext] path ...\n" unless ( -d $paths[0] ); timethese( 10, { '2File::Find' => \&try_File_Find, '1Readin_dir' => \&try_readin_dir, '0Unix_find' => \&try_unix_find, } ); sub try_File_Find { @found = (); File::Find::find( { wanted => \&wanted, # follow_fast => 1, }, @paths ); print "File::Find found ".scalar @found." matches:\n"; } sub try_readin_dir { @found = (); readin_dir( \@found, \@paths, $ext ); print "readin_dir found ".scalar @found." matches\n"; } sub try_unix_find { @found = (); my $cmd = "find @paths -type f"; open( FIND, "-|", $cmd ); while () { chomp; push @found, $_ if ( $ext eq '' or /\.$ext$/ ); } print "unix_find found ".scalar @found." matches\n"; #, join( "\n",@found,"" ); } sub wanted { push @found, $File::Find::name if ( $ext eq '' or /\.$ext$/ ); } sub readin_dir { my ( $filenames, $paths, $ext ) = @_; for my $path ( @$paths ) { $path =~ s{/+$}{}; # don't need or want trailing slash(es) opendir( my $dh, $path ) or do { warn "readin_dir: open failed for $path\n"; next }; my @subdirs = (); while ( my $file = readdir( $dh )) { next if ( $file =~ /^\.{1,2}$/ ); if ( -d "$path/$file" ) { push @subdirs, "$path/$file"; } elsif ( $ext eq '' or $file =~ /\.$ext$/ ) { push @$filenames, "$path/$file"; } } closedir( $dh ); readin_dir( $filenames, \@subdirs, $ext ) if ( @subdirs ); } }