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.

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

addDesignControlChangeNotification

but are missing this text

removeDesignControlChangeNotification

Thanks!

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. –  Yar Apr 3 '13 at 20:17
add comment

3 Answers 3

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; 
 done

Any files returned will contain addDesignControlChangeNotification but not removeDesignControlChangeNotification.

EXPLANATION:

  • 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! –  Yar Apr 3 '13 at 20:49
add comment

this should work:

FIRST=addDesignControlChangeNotification
SECOND=removeDesignControlChangeNotification
grep -l $FIRST * | while IFS= read -r FILE
do
    grep $SECOND "$FILE" &> /dev/null
    if [ $? -ne 0 ]
    then
        echo "File $FILE has $FIRST but not $SECOND"
    fi
done
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! –  Yar 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
add comment

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
add comment

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.