Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have around 500 strings and I want to search for the files which contain them inside a directory and get the file names which contain the strings. So far I've been using:

find -name 'LYFNRE.*' -exec grep -f file1.txt {} \; -print

but the problem is a string can be found in many files so it is difficult to find which strings are present and which are missing due to the huge output. Can you help me in printing the strings with their corresponding file names where they were found.

share|improve this question

3 Answers 3

The problem is that you're passing one file at a time to grep. When grep sees a single file on its command line, it assumes that you know exactly where you'r searching, so it doesn't display the file name in front of matches.

A trick to force grep to always output a file name is to also pass /dev/null (where there won't be any match ever). Some grep implementations have an option for that: -H.

Additionally, you can use -exec … {} + instead of -exec … {} \; to execute the program for many files in one go. This is faster. You should still pass /dev/null or -H, because it could happen that the command is invoked on exactly one file, either because there is a single matching file or because there are many matches requiring that grep is invoked several times and one time happens to concern a single file.

find -name 'LYFNRE.*' -exec grep -f file1.txt /dev/null {} +

GNU grep and recent BSD implementations (including OSX) support options to call grep recursively without requiring find.

grep -R --include='LYFNRE.*' -f file1.txt -H .

Alternatively, you can do recursive globbing in your shell. In zsh, this works out of the box. In bash, you need to run shopt -s globstar first, and beware that bash recurses through symbolic links to directories (unlike find or zsh).

grep -f file1.txt /dev/null **/LYFNRE.*
share|improve this answer

use egrep:

egrep -n "str1|str2|str3" file_names

-n will print line number in the specific file the string was found

share|improve this answer
    
It's not using egrep that makes a difference, it's passing the whole list of file names on the command line (and you don't explain how to do that). –  Gilles Jun 18 at 22:14
    
well that depends on the where the files are located. If there is a constant list of files, you can use: "for f in ${file_list[@]} ; do echo $f ; egrep -n str1|str2|str3 $f ; done" . if all files are in same directory: "egrep -rn "str1|str2" dir_name" . if there is a constant list of directories that include all the files, use: "for dir in ${dir_list[@]} ; do egrep -rn "str1|str2" dir_name ; done" . read man egrep for input/out specifications, but it is pretty similar to grep –  csny Jun 19 at 6:54

You should just let grep give you the filenames. GNU grep can do this:

grep -HFf ../strings.txt *

That will present you with output that looks like:

[filename]:[matched_line]

...for every match on every file in the directory. You can get line numbers as well:

grep -HnFf ../strings.txt *

...which provides...

[filename]:[line_number]:[matched_line]
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.