0

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.

2
  • Hmm, in the main dir, or main dir and subdirectories? Apr 3, 2013 at 18:59
  • I mean the dir we start the script in and all subdirectories. Sorry that wasn't clear before. Apr 3, 2013 at 20:17

3 Answers 3

1

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.

1
  • 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! Apr 3, 2013 at 20:49
2

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
2
  • Looks great, but I'm getting "Is a directory" instead of actually entering into those directories. Any idea what's wrong? Thank you +1! Apr 3, 2013 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, 2013 at 20:29
0

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .