#!/usr/bin/perl use strict; # use Data::Dumper; # you might want this die "Usage: $0 search_path search_pattern\n" unless ( @ARGV == 2 and -d $ARGV[0] ); my ( $path, $pattern ) = @ARGV; my @filelist; open( my $find, "-|", "find $path -type f -depth -print0" ) or die "Unable to run 'find $path ...'\n"; { local $/ = chr(0); # set input record separator to null byte @filelist = <$find>; chomp @filelist; # remove null byte terminations } close $find; my %found; for my $filename ( @filelist ) { # $. = 0; # (update: this line is not needed) open( my $fh, $filename ); while (<$fh>) { $found{$filename}{$.} = $_ if ( /$pattern/ ); } close $fh; } # check out how the data is stored if you want: # print Dumper( \%found ); # or pretty-print it: for my $file ( sort keys %found ) { # parse $file into directory and filename if you want for my $line ( sort {$a<=>$b} keys %{$found{$file}} ) { printf( "File <<%s>> LineNo <<%d>> matches: %s", $file, $line, $found{$file}{$line} ); } }