Roi Shidlovsky
Roi Shidlovsky

Reputation: 59

grep for a specific file with specific string in all sub-directories in perl

I have many subdirectories, some of them contain an "info.txt" file. this "info.txt" contains a line that starts with "E|email" or "O|owner". I need to extract these lines with a perl script.

in shell it looks like this:

grep --include=info.txt -rnw .  -l -e 'owner:' -e 'email:'

thank you

Upvotes: 0

Views: 288

Answers (2)

zdim
zdim

Reputation: 66883

For a flat list of directories (no further/recursive subdirectories):

perl -we'
    @ARGV = glob "*/info.txt"; 
    while (<>) { print "In $ARGV: $_" if /^(?:[eE]mail|[oO]wner)/ }'

This is shown as a one-liner for a demo, but the code can be copied into a script as it stands.

If a command-line program ("one-liner") is actually sought (in a shell script for example) then some of the above is provided by -n switch, and we can use a shell glob, so it simplifies to

perl -wne'print "In $ARGV: $_" if /^(?:[eE]mail|[oO]wner)/' */info.txt

Upvotes: 1

ikegami
ikegami

Reputation: 385725

I don't think you're interested in a shell command that uses perl. (Maybe you want to include it in a larger program, or maybe you want portability.) It would have been nice to know...

I would use File::Find::Rule.

use File::Find::Rule qw( );

for my $qfn (
   Find::File::Rule
   ->name('info.txt')
   ->in('.')
) {
   open(my $fh, '<', $qfn)
      or warn("Can't open \"$qfn\": $!\n"), next;

   while ( my $line = <$fh> ) {
      print $line
         if $line =~ /^(?:[eE]mail|[oO]wner)/;
   }
}

That does what you ask. To do what your grep one-liner does, replace

print $line
   if $line =~ /^(?:[eE]mail|[oO]wner)/;

with

if ($line =~ /^(?:[eE]mail|[oO]wner)/) {
   print "$qfn\n";
   last;
}

Upvotes: 2

Related Questions