oh5yw has asked for the wisdom of the Perl Monks concerning the following question:

I have directory called chat/ and inside it has multiple HTML-files. Extensions are .htm How can I make a script which asks user to input a string and then search all those files chat/*.htm and print every line where that string occurs? Pleas help old timer Kari
  • Comment on How to search string in all files in directory

Replies are listed 'Best First'.
Re: How to search string in all files in directory
by Anonymous Monk on Dec 10, 2008 at 13:34 UTC
Re: How to search string in all files in directory
by svenXY (Deacon) on Dec 10, 2008 at 13:34 UTC
    Hi,
    File::Find will probably help you there, but this is something that I personally would do with grep (the Unix command). It has the -r switch for recursive searches.
    Regards,
    svenXY
      Well, considering the OP only wants files from one particular directory, he doesn't need the -r option.

      But grep is still the way to go though.

Re: How to search string in all files in directory
by swampyankee (Parson) on Dec 10, 2008 at 14:28 UTC

    The first place to look is glob, since it appears that you don't want to recurse down a directory tree. As an example (NOT TESTED)

    # insert appropriate shebang line use strict; use warnings; my @files = glob("chat/*.htm"); # use something like [Hh][Tt][Mm] if y +ou're unsure about the case @files = grep { -s $_ and -f _ and -r _} @list; print "Enter search string :"; my $string = <>; # read from STDIN chomp($string); # strip off the line feed resulting from <enter> my $quoted_string = quotemeta($string); # quote all meta-characters. + Remove if not needed foreach my $file (@files) { my $filehandle; unless(open($filehandle, "<", $file)) { warn "Could not open $file because $!\n"; next; } my @contents = <$filehandle>; # presuming the files are not too la +rge chomp(@contents); close($filehandle) or die "Could't close $file because $!\n"; @contents = grep { /$quoted_string/ } @contents; if(@contents){ print "$string was found in $file:\n\t",join("\n\t",@contents), +"\n"; } }
    Warning! Code is NOT tested, and I won't even guarantee it will compile.

    Doubtless there are better ways to do this than my example. One obvious improvement could be to slurp up the entire file into a scalar, not read it into an array, by setting $/ to undef; this is probably faster. Other improvements would be to permit regex.


    Information about American English usage here and here. Floating point issues? Please read this before posting. — emc

Re: How to search string in all files in directory
by mtths (Initiate) on Dec 10, 2008 at 16:08 UTC
    this sounds quite like a task for App::Ack unless you want to reinvent the wheel

    $ cpan App::Ack

    and write some glue or just use the supplied ack script
Re: How to search string in all files in directory
by gasho (Beadle) on Dec 10, 2008 at 21:06 UTC
    use File::Find::Rule sub fullPathToFile #($StartDirectory,$SearchExpression) { my ($StartDirectory,$SearchExpression)= @_; my(@files,$IsWin1,$IsWin2,@File_Paths,$Fl,@d,$c); @files = File::Find::Rule->file()->name("$SearchExpression")->in(" +$StartDirectory"); $IsWin1=substr($StartDirectory,1,1); $IsWin2=substr($StartDirectory,0,2); #If $StartDirectory starts with D:\ or \\\\ than it is Win repla +ce / with \ if(($IsWin1 eq ':')||($IsWin2 eq '\\\\')) { foreach $Fl (@files) { @d=split(/\//,$Fl); $c=join ("\\",@d); push(@File_Paths,$c); } } else { @File_Paths=@files; } return @File_Paths; } $LocationOfTheStartDir='C:\chat'; $SearchExp='*.htm'; @AllFilePaths=fullPathToFile($LocationOfTheStartDir,$SearchExp); foreach $InputFile (@AllFilePaths){ @AllLinesFromTheFile = `type $InputFile`; foreach $line (@AllLinesFromTheFile){ if ($line=~/DesiredString/){ print "$line"; } } @AllLinesFromTheFile=(); }
    (: Life is short enjoy it :)
      No help got only this Software error: syntax error at testi7.cgi line 8, near "use File::Find::Rule sub fullPathToFile #($StartDirectory,$SearchExpression) " Execution of testi7.cgi aborted due to compilation errors.
        Most likely you have not installed File::Find::Rule Try this code without calling any modules
        sub fullPathFileName #($StartDirectory,$RegularExpression) { #my ($StartDirectory,$WhildCardSearch)= @_; my ($StartDirectory,$RegularExpression)= @_; my(@A,$e,$C,@B,$a,@C,@Dir,$InputDir,@AllTestSuitefiles,@TestSuitef +iles,$p,@FullPath); #Purpose is to extract all paths to directories and subdirectories @A=`dir $StartDirectory /s/w ` ; foreach $e (@A) { $C=substr($e,0,10); #Extract only string that starts with Directory if($C eq " Directory") { push(@B,$e); } } # Directory of C:\cr1_qc\crnqcV3\CM\Bering\Results\object_test_ +mssql\Root\DirectorySuite\GroupsandRolesSuite\OutputPages # I want to start from C: foreach $a (@B) { push(@C,substr($a,14)); } #Remove lash char that is whitespace @Dir=trim(@C); foreach $InputDir (@Dir) { opendir(ODH,"$InputDir")|| die "Can't open dir\n"; @AllTestSuitefiles=readdir(ODH); # @TestSuitefiles=glob("$WhildCardSearch"); closedir(ODH); # Find all files @TestSuitefiles=grep(m/$RegularExpression/,@AllTestSuitefiles) +; foreach $p (@TestSuitefiles) { push(@FullPath,"$InputDir\\$p"); } } return @FullPath; }#fullPathFileName $LocationOfTheStartDir='C:\chat'; $SearchExp='*.htm'; @AllFilePaths=fullPathToFile($LocationOfTheStartDir,$SearchExp); foreach $InputFile (@AllFilePaths){ @AllLinesFromTheFile = `type $InputFile`; foreach $line (@AllLinesFromTheFile){ if ($line=~/DesiredString/){ print "$line"; } } @AllLinesFromTheFile=(); }
        (: Life is short enjoy it :)