I use the following command to search multiple files recursively and find the number of lines in each file in which the string is found

    grep -nr "the_string" /media/slowly/DATA/lots_of_files > output.txt

The result is as follows

    /media/slowly/DATA/lots_of_files/lots_of_files/file_7.txt:6:the_string is in this sentence.
    /media/slowly/DATA/lots_of_files/lots_of_files/file_7.txt:9:the_string is in this sentence too.

The output shows the filename line number and all text in that line including the string

I've also figured out how to print just the specific lines of a file containing the string using the following command

    sed '3!d' /media/slowly/DATA/lots_of_files/lots_of_files/file_3.txt > print.txt
    sed '6!d' /media/slowly/DATA/lots_of_files/lots_of_files/file_7.txt >> print.txt
    sed '9!d' /media/slowly/DATA/lots_of_files/lots_of_files/file_7.txt >> print.txt

I created the above commands manually by reading the line numbers and filenames

I have one question


What can be done to combine two steps into a single command? I'm thinking piping the line number and filename into sed and printing the line I'm having a problem with the order in which the grep output is generated


Same as above but also print the 2 lines before and 2 lines after the line containing the string (total of 5 lines)? I'm thinking piping the line number and the filename in sed and printing all the required lines somehow

Thank you very much

Best Answer

If i am understanding the question correctly, you can accomplish this with one grep command.

For Q1a, your grep output can suppress the filename using -h , e.g..

grep -hnr "the_string" /media/slowly/DATA/lots_of_files > output.txt

For Q1b, your grep output can include lines preceding and following matched lines using -A and -B , e.g..

grep -hnr -A2 -B2 "the_string" /media/slowly/DATA/lots_of_files > output.txt

The output will contain a separator between matches, which you can suppress with --no-group-separator , e.g..

grep -hnr -A2 -B2 --no-group-separator "the_string" /media/slowly/DATA/lots_of_files > output.txt

Note that the output uses a different delimiter for matching lines ( : ) and context lines ( - ).