Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Finding names in files

by gzayzay (Sexton)
on Mar 29, 2006 at 17:14 UTC ( [id://540007]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks;

Today was a beautiful day watching the Solar eclipse on NASA TV. However, let me get to the point. I am trying to write a script that will check a file to see if the first 20 lines does not contain the word "DAVE". While searching for DAVE, I will like for the script to ignore case sensitivity i.e Dave and DAVE should be consider the same. If the first 20 lines of the file does not have dave, I will like to print the path of that file to a folder I called "input". I have used the find function to generate the paths to every files that I will love to search and store it in a file called "output". My problem is, I am not able to return the name of the file if it does not contain dave and i have not been able to make the search case insensitive.

Therefore, I am kindly asking any monk to help me. Thanks for your assistance.

use strict; use File::Find; my $count; my $path = "C:/hello/"; my $output = $path."Output.txt"; my $input = $path."Input.txt"; START: print ("Enter the name of your file >> "); chomp (my $name = <STDIN>); if(length($name)==0) { print (STDERR "\nYour did not respond!!\n"); goto START; } else { my $spath = $path.$name; open(FM, ">$output") && open(AM, ">$input") || die ("Cannot open, +$!\n"); find(\&search, "$spath"); close FM; open(SW, $output)||die ("Cannot open, $!\n"); while(<SW>) { my $flag = 1; chomp; if (open(ETA, $_)) { $count = 0; while(<ETA>) { foreach($_){$count++;}; if (($_ ne "Dave") && ($count <= 20)) { $flag = 0; } } if ($flag == 0) { #I am trying to print the name of the file containg "D +ave" in the first 20 lines print (AM "$_\n"); } } else { die ("Cannot open [$_], $!\n"); } }close AM; close SW; } sub search { if (((/\.c/)&&(!(/\.com/)))|(/\.h/)|(/\.pr/)) { print (FM "$File::Find::name\n"); } }

Replies are listed 'Best First'.
Re: Finding names in files
by davidrw (Prior) on Mar 29, 2006 at 17:28 UTC
    first, a couple command-line solutions:
    #bash: for f in `find /tmp/files/`; do head -20 $f | grep -q -i dave && echo +$f >> list.txt ; done perl -lne 'do { print $ARGV; last } if /DAVE/i; last if $. == 20' `fi +nd /tmp/files` >> list.txt
    Now, addressing your code, couple starting points: note that $. (see perlvar) can be used instead of $count ; instead of string matching 'Dave' (which is why the case has to be exact), use a regular expression of /dave/i (or maybe /\bdave\b/i) -- see perlre for tons of regexp info.
    Also, why use File::Find if you're given a single filename to start with?
      I am searching multiples files that end with .c, .h, and .pr (56 in total). That is why I am using File::Find.
        consider File::Find::Rule to simplify things:
        my @files = File::Find::Rule->file()->name->( '*.c', '*.h', '*.pr' )-> +in(qw( /tmp/dir1 /tmp/dir2 ));
Re: Finding names in files
by ww (Archbishop) on Mar 29, 2006 at 17:28 UTC
    narrowly re case insensitivity: regexen make it easy.
    Instead of your
    foreach($_){$count++;}; 033: if (($_ ne "Dave") && ($count <= 20)) 034: {
    a small change such as (untested):
    foreach($_){$count++;}; 033: if (( $_ !~ /dave/i ) && ($count <= 20)) 034: {
    where the "!~" and the ".../i" make the regex fail if any variant of DAVE, dave, Dave, etc is present...

    However, my quick read and slow mind make me wonder if my logic (which follows yours) is correct -- ie, whether you really want a negative there... Resolution left as an exercise for the student...

      Hey WW;

      I was following your entire comments until the last two lines. Are you a philosopher...LOL. Anyway, Thanks for the help.

Re: Finding names in files
by duff (Parson) on Mar 29, 2006 at 17:42 UTC

    Perl keeps track of the current line number for you in the $. variable, so no need to count them your self.

    Here's an implementation you can learn from (hopefully :-):

    for my $file (@files) { my $has_dave; open my $fh, "<", $file or warn("Can't open $file - $!\n"), next; while (<$fh>) { last if $. > 20; $has_dave = 1 if /dave/i; } print "$file\n" unless $has_dave; }
      Thanks duff,

      However, I do not understand the following part of your code.

      for my $file (@files)

      Why are You using $file(@files), could you kindly explain that to me.



        That syntax puts the default variable (i.e., the array element that he's working on) into $file so he can use that in his loop instead of $_ or $file=$_;

        No muss, no fuss
Re: Finding names in files
by zer (Deacon) on Mar 29, 2006 at 17:32 UTC
    $_ is the current filename within that directory
    $File::Find::name is the complete pathname to the file.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://540007]
Approved by idsfa
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (6)
As of 2024-03-29 01:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found