find path -type f -print0 | xargs -0 grep -i -n pattern
####
path/filename:line#:content of line containing pattern
path/subdir/filename:line#:another line with pattern in it
####
#!/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} );
}
}