Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

How can I grep for files in a directory structure that have this text


but are missing this text



Note: I mean the directory the script starts in and all subdirectories.

share|improve this question
Hmm, in the main dir, or main dir and subdirectories? – Rich Homolka Apr 3 '13 at 18:59
I mean the dir we start the script in and all subdirectories. Sorry that wasn't clear before. – Dan Rosenstark Apr 3 '13 at 20:17
up vote 1 down vote accepted

Here's one that is loosely based on Rich Homolka's answer, but works on directory trees:

find . -type f  -exec grep -l addDesignControlChangeNotification {} \; | 
 while IFS= read -r file; do 
   grep -q removeDesignControlChangeNotification "$file" > /dev/null ; 
   [ $? -ne 0 ] && echo $file; 

Any files returned will contain addDesignControlChangeNotification but not removeDesignControlChangeNotification.


  • find . -type f -exec grep -l foo {} \;: This will print all files in any subdirectory of the current directory that contain the string foo. The -l flag causes grep to only print the names of matching files.

  • while read file : this iterates through each file found above, saving its name in the variable $file.

  • grep -q bar "$file" > /dev/null : this comand loks for the string bar in each of the files that contained foo.

  • [ $? -ne 0 ] && echo $file; : If the return value ($?) of the grep command was 0 (i.e. if the string was not in the file), print the name of the file.

share|improve this answer
Awesome, I'm using find . -name '*.m' -type f -exec grep -l addDesignControlChangeNotification {}... which I added myself since I didn't mention it in the question ;) Thanks! – Dan Rosenstark Apr 3 '13 at 20:49

this should work:

grep -l $FIRST * | while IFS= read -r FILE
    grep $SECOND "$FILE" &> /dev/null
    if [ $? -ne 0 ]
        echo "File $FILE has $FIRST but not $SECOND"
share|improve this answer
Looks great, but I'm getting "Is a directory" instead of actually entering into those directories. Any idea what's wrong? Thank you +1! – Dan Rosenstark Apr 3 '13 at 20:17
@Yar, you can add an -r to the first grep command if you want to recurse directories. Or you can use my answer ;). – terdon Apr 3 '13 at 20:29

One liner:

comm -2 -3 <(grep -rl addDesignControlChangeNotification     . | sort ) \
           <(grep -rl removeDesignControlChangeNotification  . | sort )

grep -r is a recursive grep, <() is process substitution, and comm shows you lines that a pair of (sorted) files do/don't have in common. In this case we only want the column 1 output: lines in the first file (where "file" is really grep output) which are not in the second.

share|improve this answer

Your Answer


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.