Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I have little problem figuring out how to get a list of files that has:

  1. string "/fo" in it
  2. But does not have string "/mo"

I'm trying to figure out that in folder with lot of text files... My unsuccessful tries...

  • grep -lE '(?=/fo)^(?=/mo)' *
  • grep -E '(fo)(mo)' *

I'm stuck here... Suggestions?

share|improve this question
1  
possible duplicate of grep for "term" and exclude "another term" –  Dennis Mar 11 '13 at 11:10
2  
I'd say not a duplicate. This question is concerned with occurrence in the entire file and wants the file name, the other one is about matching single lines and doesn't need the file name. That makes this distinct and non-trivial. I personally wouldn't know how to do it without, say, awk. And indeed the answers on the other question do not solve this problem. –  user112553 Mar 11 '13 at 11:33
    
@Dennis: As user112553 answered, that is not same question that I've asked... –  confiq Mar 11 '13 at 12:56
    
Your first paragraph sounded to me like you were searching for /fo in the files' names, not the files' contents. –  Dennis Mar 11 '13 at 13:22
    
I edited the question... –  confiq Mar 11 '13 at 14:11

1 Answer 1

up vote 2 down vote accepted

I don't think you can do this with one pass using grep.

A two-pass grep solution

This solution uses find to pass files in current directory to a while-loop, which in turn does the desired grep'ing:

find . -maxdepth 1 -type f -print0 | while IFS= read -r -d $'\0' file; do
  grep -q '/mo' "$file" || grep -l '/fo' "$file" 
done

A one-pass GNU awk solution

parse.awk

BEGINFILE { f1 = f2 = 0 }
$0 ~ pat1 { f1 = 1 }
$0 ~ pat2 { f2 = 1 }
ENDFILE   { if(f1 && !f2) print FILENAME }

Run it like this:

awk -f parse.awk pat1='/fo' pat2='/mo' *

Explanation

GNU awk has the BEGINFILE and ENDFILE feature which are blocks executed at the beginning and end of an input-file. This enables us to flip flags when the patterns are seen.

The above example sets the two flags, f1 and f2, based on if pat1 and pat2 are found in the current input-file. Thus the ENDFILE block knows if both patterns were present in the current input-file, and can perform the appropriate test.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.