1

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 4

5

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!

3

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
  • @muru can help with syntax of saving the filename to a file instead of printing it Apr 19, 2018 at 5:36
  • @user1573232 just put a > output-file at the end of the command
    – muru
    Apr 19, 2018 at 5:41
3
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'
1

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)

You must log in to answer this question.

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