find the last 5 lines, in each text file in a folder, that contain a matching pattern

Viewed 69

I am a Unix Newbie and have been trying to get around this one task for quite some time now. Would be great if someone could help me.

Problem - I need to loop through a folder, into each .txt file and then fetch the last 5 lines that have a specific word (ex : test)

I am trying to traverse through the folder, into each file, and print the last 5 lines where the word 'test' has occured.

for example - if the word 'test' is found in line numbers 1,3,5,7,9,12,14,15. then I need to only print the whole line at line number 7,9,12,14,15.(i.e the last 5 lines that have the occurrence of this word)

I am somehow not being able to upload images in my question but I hope this info helps: File 1 - [Here there are 7 occurances of the word test and I need just the last 5] File 2 - [Here there are 6 occurances of the word test and I need just the last 5]

The command I figured out is : cd to folder path:

find . -type f -exec grep -iH "test" {} + | tail -n5; tail -n0 | grep -i test

This command works but it prints the last 5 lines and then exits. It does not go into another file.(since it already has found its last 5 lines with the matching word)

In my case, however I want the output to be the last 5 lines of 'each' file.

Can someone please help. Thank you in advance.

2 Answers

First problem:

You can't use a pipe in the exec part of the find command. As a workaround you start a shell inside the exec part which takes a command which now can include a pipe.

To let the new started shell know where the command starts and ends, simply use single quotes.

I need to loop through a folder, into each .txt

find . -name '*.txt'

where the word 'test' has occured.

find . -name '*.txt' -exec grep "test" {} \;

and print the last 5 lines

OK, here we need to start another shell inside the exec part of find:

find . -name '*.txt' -exec sh -c 'grep "test" {} | tail -n5 ' \;

With UNIX tools you could:

tac file | grep -m5 PATTERN 

To combine this with find you need to exec a shell because of the pipe between tac and grep:

find . -type f -exec bash -c 'tac "${1}" | grep -m5 PATTERN' -- {} \;
Related