M BUZZ CRAZE NEWS
// general

How to grep for two patterns in multiple files

By Jessica Wood

I have multiple files in multiple directories, and I need a grep command which can return the output only when both the patterns are present in the file. The patterns are like AccessToken and Registrationrequest. The patterns are not in the same line. AccessToken can be in one line and Registrationrequest can be in another line. Also search the same recursively across all files in all directories.

Tried

grep -r "string1” /directory/file | grep "string 2”
grep -rl 'string 1' | xargs grep 'string2' -l /directory/ file
grep -e string1 -e string2 

Nothing works

Can anyone please help?

0

4 Answers

The following command can print out when the file matches the search criteria:

grep -Zril 'String1' | xargs -0 grep -il 'String2'

Here is an example:

~/tmp$ ls
Dir1 Dir2 File1 File2
cat File1
AccessToken is not here
Registrationrequest it is here
cat File2
iAccess
ByteMe Registrationrequest

I copied both File1 and File2 into the Dir1 and Dir2 for testing:

~/tmp$ grep -Zril 'AccessToken' | xargs -0 grep -il 'Registrationrequest'
File1
Dir2/File1
Dir1/File1

Then if you want to see what is in the files add the following to the end of the search:

xargs grep -E "AccessToken|Registrationrequest"

Example:

~/tmp$ grep -Zril 'AccessToken' | xargs -0 grep -il 'Registrationrequest' | xargs grep -E "AccessToken|Registrationrequest"
File1:AccessToken is not here
File1:Registrationrequest it is here
Dir2/File1:AccessToken is not here
Dir2/File1:Registrationrequest it is here
Dir1/File1:AccessToken is not here
Dir1/File1:Registrationrequest it is here

Hope this helps!

Just in case the files are very large and making two passes on them is expensive and you want just the filenames, using find+awk:

find . -type f -exec awk 'FNR == 1 {a=0; r=0} /AccessToken/{a=1} /Registrationrequest/{r=1} a && r {print FILENAME; nextfile}' {} +
  • we set two flag variables a and r for when the corresponding patterns were found, cleared at the start of each file (FNR == 1)
  • when both variables are true, we print the filename and move on to the next file.
2
grep -Erzl 'STR1.*STR2|STR2.*STR1'

where option -z ends up slurping the files as a single line.

More precisely:

grep -Erzl 'AccessToken.*Registrationrequest|Registrationrequest.*AccessToken'

while loop

This may not be as clever or resource-effective as other solutions, but it works:

while read -rd '' filename; do if grep -q "AccessToken" "$filename" && grep -q "Registrationrequest" "$filename" then echo "$filename" fi
done < <(find . -type f -print0)

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy