Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number

I need "Antigrep"

by tphyahoo (Vicar)
on Aug 15, 2006 at 17:52 UTC ( #567510=perlquestion: print w/replies, xml ) Need Help??

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

I'm doing cleanup on a large codebase.

It would be useful for me to identify files NOT containing certain patterns, eg files missing an initiation or configuration string, or that kind of thing.

I initially thought I could do this with grep -vl, but no dice. It doesn't work, because grep -vl compares line by line, so if any LINE doesn't contain the pattern, the file is flagged as not containing the pattern.

I tracked down a script called grepcat which supposedly does what I want (haven't tried it).

Seems a bit kludgy to me though, and a good candidate for doing in perl instead.

So, anybody got a quickie perl script to do the OPPOSITE of grep? I just want the filenames, not the non matching lines. Should work as follows

hartman@ds0207:~/filesContainingArena> find | xargs -ti cat {} cat . cat: .: Ist ein Verzeichnis cat ./a a cat ./b b a cat ./c c a hartman@ds0207:~/filesContainingArena> c * # should return + files not containing c, eg a and b, but not c. bash: command not found hartman@ds0207:~/filesContainingArena> grep -vl c * #unfortunately thi +s doesn't work a b c hartman@ds0207:~/filesContainingArena>

Alternatively, I should be able to do antigrep with

find | xargs I'd really like to do this in a one-liner, but can't quite think how.

Much obliged!

Replies are listed 'Best First'.
Re: I need "Antigrep"
by Fletch (Chancellor) on Aug 15, 2006 at 18:04 UTC

    Erm, just grep for the pattern and invert the sense of exit code (if grep exits successfully (the file does contain the pattern at least once) then you don't want that file; if it exits with an error you do want it (since it didn't contain the pattern at all)).

    Update: Actually if you have GNU grep (i.e. don't know if this is a kosher POSIX grep option) just use the -L flag:

    -L, --files-without-match only print FILE names containing no match
      /me smacks self on head...
      Is that a bash (non perl) solution?

      If so, could you explain how I do that?

Re: I need "Antigrep"
by ikegami (Pope) on Aug 15, 2006 at 17:57 UTC
    my $pattern = shift(@ARGV); my $re = qr/$pattern/; FILE: foreach my $filename (@ARGV) { open(my $fh, '<', $filename) or do { warn("Unable to open $filename: $!\n"); next; }; while (<$fh>) { next FILE if /$re/; } print("$filename\n"); }


      Unfortunately doesn't work.
      hartman@ds0207:~/filesContainingArena> find | xargs hartman@ds0207:~/f +ilesContainingArena> find | xargs ./ c . ./a ./b ./c
      Maybe I can use that as a starting point though, so....

      UPDATE: Thanks for the update, Ikegami :)

        Fixed. $fh was going out of scope prematurely when I used

        if (!open(my $fh, '<', $filename)) { warn("Unable to open $filename: $!\n"); next; }

        I'm not sure how xargs works, but I tested it using c *

Re: I need "Antigrep"
by grep (Monsignor) on Aug 15, 2006 at 20:19 UTC
    I knew my nemesis would come after me someday.

    Mynd you, mønk bites Kan be pretti nasti...
Re: I need "Antigrep"
by imp (Priest) on Aug 15, 2006 at 18:25 UTC
    grep -c something * | awk -F : '$2 == 0 {print $1}'
    This approach counts the number of occurences of that string in the files matched by *, and has awk print out the matches where that number is 0.
Re: I need "Antigrep"
by jwkrahn (Monsignor) on Aug 15, 2006 at 21:02 UTC
    perl -lne'$found += /c/; eof && do { $found ? undef $found : print $AR +GV }' *
Re: I need "Antigrep"
by leocharre (Priest) on Aug 15, 2006 at 22:34 UTC

    I think I get what you are asking.. ?

    sick this in ~/bin/musthave and chmod 0755

    #!/usr/bin/perl use strict; my ($what,$file)= @ARGV; open(HANDLE, $file); my @match = grep { /$what/ } <HANDLE>; close HANDLE; scalar @match or print STDERR "$file is missing $what\n"; exit;

    then do ..
     $ find /where/my/stuff -type f -iname "*txt" -exec musthave 'I WANT THIS INN HERE' '{}' \;

    What I like doing with these little things that are useful and may be used on one or a thousand files.. is to isolate the problem to *one* file, and use the system to call it multiple times (or antoher script to iterate) as needed. That way you isolate the problem into smaller parts.

Re: I need "Antigrep"
by gasho (Beadle) on Aug 15, 2006 at 19:46 UTC
    Try this
    #Unix # Example 2: grep for lines that do not match the supplied regexp expr +essions [gasho:~]$ echo ' cat dog mouse horse' | grep -v -e 'mouse' -e 'dog' cat horse #Perl @filenames = qw(cat dog mouse horse); @donotmatch = grep {!(/cat/||/horse/)} @filenames;
    (: Life is short enjoy it :)

Log In?

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

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (6)
As of 2021-10-28 12:41 GMT
Find Nodes?
    Voting Booth?
    My first memorable Perl project was:

    Results (96 votes). Check out past polls.