7535

How do I find all files containing a specific string of text within their file contents?

The following doesn't work. It seems to display every single file in the system.

find / -type f -exec grep -H 'text-to-find-here' {} \;
5
  • 43
    remember that grep will interpret any . as a single-character wildcard, among others. My advice is to alway use either fgrep or egrep. Commented Oct 28, 2013 at 11:54
  • 15
    anyway, you were almost there! Just replace -H with -l (and maybe grep with fgrep). To exclude files with certain patterns of names you would use find in a more advanced way. It's worthwile to learn to use find, though. Just man find. Commented Oct 28, 2013 at 12:01
  • 12
    find … -exec <cmd> + is easier to type and faster than find … -exec <cmd> \;. It works only if <cmd> accepts any number of file name arguments. The saving in execution time is especially big if <cmd> is slow to start like Python or Ruby scripts.
    – hagello
    Commented Jan 28, 2016 at 5:16
  • 2
    Does this answer your question? How can I use grep to find a word inside a folder?
    – NAND
    Commented May 19, 2020 at 20:42
  • you probably meant . instead of / / means start at the root directory, which is of course the entire filesystem Commented May 17 at 19:17

56 Answers 56

13681

Do the following:

grep -Rnw '/path/to/somewhere/' -e 'pattern'
  • -r or -R is recursive ; use -R to search entirely
  • -n is line number, and
  • -w stands for match the whole word.
  • -l (lower-case L) can be added to just give the file name of matching files.
  • -e is the pattern used during the search

Along with these, --exclude, --include, --exclude-dir flags could be used for efficient searching:

  • This will only search through those files which have .c or .h extensions:

    grep --include=\*.{c,h} -rnw '/path/to/somewhere/' -e "pattern"
    
  • This will exclude searching all the files ending with .o extension:

    grep --exclude=\*.o -rnw '/path/to/somewhere/' -e "pattern"
    
  • For directories it's possible to exclude one or more directories using the --exclude-dir parameter. For example, this will exclude the dirs dir1/, dir2/ and all of them matching *.dst/:

    grep --exclude-dir={dir1,dir2,*.dst} -rnw '/path/to/search/' -e "pattern"
    

This works very well for me, to achieve almost the same purpose like yours.

For more options, see man grep.

5
  • 96
    use --exclude. like "grep -rnw --exclude=*.o 'directory' -e "pattern"
    – rakib_
    Commented Jun 6, 2013 at 8:29
  • 186
    it's worth noting: it seems the r option is lazy (traverses depth-first, than stops after the first directory), while R is greedy (will traverse the entire tree correctly). Commented Mar 24, 2015 at 15:09
  • 61
    Note(especially for newbies): The quotation marks in the above command are important.
    – madD7
    Commented Dec 22, 2015 at 12:37
  • 3
    For me it was useful to add the -I option to skip all binary files.
    – Ivan Gorin
    Commented Nov 19, 2022 at 22:03
  • -rnw is case-sensitive and whole word only. For a broader search change -rnw to -rni yielding matches for whole or partial words regardless of letter case.
    – MikeOnline
    Commented Nov 14, 2023 at 18:42
2316

Use grep -ilR:

grep -Ril "text-to-find-here" /
  • i stands for ignore case (optional in your case).
  • R stands for recursive.
  • l stands for "show the file name, not the result itself".
  • / stands for starting at the root of your machine.
4
  • 152
    Based on my experience, the -i makes it slow down a lot, so don't use it if not necessary. Test it in a certain dir and then generalise. It should be completed within few minutes. I think a regular expression would make it slower. But my comments are based on suppositions, I suggest you to test it with time in front of the line.
    – fedorqui
    Commented Jun 6, 2013 at 8:14
  • 36
    You can replace / with path to directory grep -Ril "text-to-find-here" ~/sites/ or use . for current directory grep -Ril "text-to-find-here" .
    – Black
    Commented Jan 28, 2016 at 12:19
  • Very slow though. Not recommended for large file systems.
    – raaj
    Commented Oct 11, 2021 at 7:03
  • on my distro grep used lowercase "R" so it was => grep -ril "name" /, but uppercase R didn't work.
    – JDuarteDJ
    Commented Feb 7, 2023 at 18:35
470

You can use ack. It is like grep for source code. You can scan your entire file system with it.

Just do:

ack 'text-to-find-here'

In your root directory.

You can also use regular expressions, specify the filetype, etc.


UPDATE

I just discovered The Silver Searcher, which is like ack but 3-5x faster than it and even ignores patterns from a .gitignore file.

4
  • 77
    Very useful, simple and fast. Warning: "On Debian-derived distros, ack is packaged as "ack-grep" because "ack" already existed" (from beyondgrep.com/install). You may end up running a Kanji code converter on those Linuxes...
    – Jose_GD
    Commented Sep 20, 2013 at 13:32
  • 14
    ack or ack-grep has nice highlights, but find+grep when proper used is much better in performance Commented Feb 11, 2015 at 9:00
  • 39
    Note that ripgrep is faster than anything else mentioned here, including The Silver Searcher and plain 'ol grep. See this blog post for proof. Commented Oct 14, 2017 at 4:01
  • on Ubuntu and LinuxMint, use $ ag 'what I want' ./
    – Russo
    Commented Feb 22, 2023 at 13:34
303

You can use:

grep -r "string to be searched" /path/to/dir

The r stands for recursive and so will search in the path specified and also its sub-directories. This will tell you the file name as well as print out the line in the file where the string appears.

Or a command similar to the one you are trying (example: ) for searching in all javascript files (*.js):

find . -name '*.js' -exec grep -i 'string to search for' {} \; -print

This will print the lines in the files where the text appears, but it does not print the file name.

In addition to this command, we can write this too: grep -rn "String to search" /path/to/directory/or/file -r: recursive search n: line number will be shown for matches

1
  • 5
    Thank you for the 'find' version! It is so important to be able to filter by '.js' or '.txt', etc. Nobody wants to spend hours waiting for grep to finish searching all the multi-gigabyte videos from the last family vacation, even if the command is easier to type.
    – mightypile
    Commented Aug 16, 2017 at 15:10
168

Recursive and case insensitive grep with line numbers:

grep -inr "Text" folder/to/be/searched/
2
  • if you add -A3 is even better
    – albanx
    Commented Feb 24, 2016 at 10:43
  • -i is for case insensitive, -n shows the line number and -r recursive reads all the file in subdirectory
    – user8234870
    Commented Feb 23, 2022 at 5:48
138

grep (GNU or BSD)

You can use grep tool to search recursively the current folder, like:

grep -r "class foo" .

Note: -r - Recursively search subdirectories.

You can also use globbing syntax to search within specific files such as:

grep "class foo" **/*.c

Note: By using globbing option (**), it scans all the files recursively with specific extension or pattern. To enable this syntax, run: shopt -s globstar. You may also use **/*.* for all files (excluding hidden and without extension) or any other pattern.

If you've the error that your argument is too long, consider narrowing down your search, or use find syntax instead such as:

find . -name "*.php" -execdir grep -nH --color=auto foo {} ';'

Alternatively, use ripgrep.

ripgrep

If you're working on larger projects or big files, you should use ripgrep instead, like:

rg "class foo" .

Checkout the docs, installation steps or source code on the GitHub project page.

It's much quicker than any other tool like GNU/BSD grep, ucg, ag, sift, ack, pt or similar, since it is built on top of Rust's regex engine which uses finite automata, SIMD and aggressive literal optimizations to make searching very fast.

It supports ignore patterns specified in .gitignore files, so a single file path can be matched against multiple glob patterns simultaneously.


You can use common parameters such as:

  • -i - Insensitive searching.
  • -I - Ignore the binary files.
  • -w - Search for the whole words (in the opposite of partial word matching).
  • -n - Show the line of your match.
  • -C/--context (e.g. -C5) - Increases context, so you see the surrounding code.
  • --color=auto - Mark up the matching text.
  • -H - Displays filename where the text is found.
  • -c - Displays count of matching lines. Can be combined with -H.
1
  • 2
    I also find extended globbing useful. But keep in mind that if there are really huge number of files, you can get a "Argument list too long" error. (Simple globbing is also prone to this kind of error).
    – Yoory N.
    Commented Nov 30, 2017 at 6:47
124

List of file names containing a given text

First of all, I believe you have used -H instead of -l. Also you can try adding the text inside quotes followed by {} \.

find / -type f -exec grep -l "text-to-find-here" {} \; 

Example

Let's say you are searching for files containing specific text "Apache License" inside your directory. It will display results somewhat similar to below (output will be different based on your directory content).

bash-4.1$ find . -type f -exec grep -l "Apache License" {} \; 
./net/java/jvnet-parent/5/jvnet-parent-5.pom
./commons-cli/commons-cli/1.3.1/commons-cli-1.3.1.pom
./io/swagger/swagger-project/1.5.10/swagger-project-1.5.10.pom
./io/netty/netty-transport/4.1.7.Final/netty-transport-4.1.7.Final.pom
./commons-codec/commons-codec/1.9/commons-codec-1.9.pom
./commons-io/commons-io/2.4/commons-io-2.4.pom
bash-4.1$ 

Remove case sensitiveness

Even if you are not use about the case like "text" vs "TEXT", you can use the -i switch to ignore case. You can read further details here.

4
  • 2
    Which is what this command does: find will pass all the paths it finds to the command grep -l "text-to-find-here" <file found>". You may add restrictions to the file name, e.g. find / -iname "*.txt" to search only in files which name ends in .txt
    – Mene
    Commented Apr 20, 2017 at 13:46
  • 1
    @Auxiliary - included a sample output to avoid any confusion for the readers.
    – lkamal
    Commented Oct 7, 2017 at 5:56
  • 3
    @Mene It's a truly sad state that Auxiliary's comment has more votes than yours...even if their comment is from 2014 and yours is 2017 that their comment has 6 when it should have exactly 0 and yours only had one (now two) isn't something I'd like to believe.
    – Pryftan
    Commented May 1, 2018 at 23:01
  • @Mene That being said -iname is case-insensitive which means it would also find .TXT files, for example, as well as TxT and TXt and so on.
    – Pryftan
    Commented May 1, 2018 at 23:04
79

This grep command will give you a precise result when you are searching for specific text on Linux -

grep -inRsH "Text to be searched" /path/to/dir (it can be '.')

  • i stands for ignore case distinctions

  • R stands for recursive and it also include symlinks. It is better to use 'R' instead of 'r'

  • n stands for "it will print line number".

  • s stands for "suppress error messages"

  • H stands for "it will print the file name for each match"

2
  • 1
    but this doesn't display the "file" that contains that text
    – FiruzzZ
    Commented Jun 29, 2022 at 18:05
  • this combination will give you lineno, filename along with the text that you have searched. @FiruzzZ try it once Commented Jun 30, 2022 at 7:11
72

If your grep doesn't support recursive search, you can combine find with xargs:

find / -type f | xargs grep 'text-to-find-here'

I find this easier to remember than the format for find -exec.

This will output the filename and the content of the matched line, e.g.

/home/rob/file:text-to-find-here

Optional flags you may want to add to grep:

  • -i - case insensitive search
  • -l - only output the filename where the match was found
  • -h - only output the line which matched (not the filename)
2
  • 4
    This is equivalent to grep 'text-to-find-here' without file name if find does not find anything. This will hang and wait for user input! Add --no-run-if-empty as an option to xargs.
    – hagello
    Commented Jan 28, 2016 at 5:46
  • 4
    This combination of find and xargs does not work as intended if file or directory names contain spaces (characters that xargs interprets as separators). Use find … -exec grep … +. If you insist on using find together with xargs, use -print0 and -0.
    – hagello
    Commented Jan 28, 2016 at 5:50
56

There's a new utility called The Silversearcher

sudo apt install silversearcher-ag

It works closely with Git and other VCS. So you won't get anything in a .git or another directory.

You can simply use

ag "Search query"

And it will do the task for you!

1
  • 1
    Good call!. I downloaded it and used it first time. The output results are very informative and colourful and very helpfull. This prog will stay in my machine for ever. I have also put it on my "Install a new computer" list of programs. Cheers!!
    – joe_evans
    Commented Jul 6, 2020 at 15:01
55
grep -insr "pattern" *
  • i: Ignore case distinctions in both the PATTERN and the input files.
  • n: Prefix each line of output with the 1-based line number within its input file.
  • s: Suppress error messages about nonexistent or unreadable files.
  • r: Read all files under each directory, recursively.
6
  • 3
    Can you explain how your answer improves upon the other answers, or how it is sufficiently different from them? Commented Feb 26, 2016 at 6:10
  • not much complex to remember, will cover all patterns(case-senstivity -> off, includes file-names and line number and will do recursively search etc) and using "*" in the end will search all directories (no need to specify any path or directory name).
    – enfinet
    Commented Feb 26, 2016 at 6:15
  • Sorry, I should've been clearer: it would be great if you could include that explanation in your answer. As it stands, especially with so many other similar answers already, it is hard to see from such a short answer what the benefit of trying it over the accepted answer or one of the upvoted ones would be. Commented Feb 26, 2016 at 6:35
  • 7
    @AmosM.Carpenter One thing I love about this answer is pointing out the suppress argument, which can help filter out noise that doesn't matter to getting the results we actually want. Grep prints errors like, "Function not implemented", "Invalid Argument", "Resource unavailable", etc. etc on certain "files". Commented Feb 20, 2017 at 5:58
  • @leetNightshade: I'm assuming you're addressing your comment to me because I asked for an explanation on the sparse original post. Please see Fabio's great revision for my previous comments to make sense. Commented Feb 20, 2017 at 11:59
52

How do I find all files containing specific text on Linux? (...)

I came across this solution twice:

find / -type f -exec grep -H 'text-to-find-here' {} \;


If using find like in your example, better add -s (--no-messages) to grep, and 2>/dev/null at the end of the command to avoid lots of Permission denied messages issued by grep and find:

find / -type f -exec grep -sH 'text-to-find-here' {} \; 2>/dev/null

find is the standard tool for searching files - combined with grep when looking for specific text - on Unix-like platforms. The find command is often combined with xargs, by the way.

Faster and easier tools exist for the same purpose - see below. Better try them, provided they're available on your platform, of course:

Faster and easier alternatives

RipGrep - fastest search tool around:

rg 'text-to-find-here' / -l

The Silver Searcher:

ag 'text-to-find-here' / -l

ack:

ack 'text-to-find-here' / -l

Note: You can add 2>/dev/null to these commands as well, to hide many error messages.


Warning: unless you really can't avoid it, don't search from '/' (the root directory) to avoid a long and inefficient search! So in the examples above, you'd better replace '/' by a sub-directory name, e.g. "/home" depending where you actually want to search...

0
52

Use pwd to search from any directory you are in, recursing downward

grep -rnw `pwd` -e "pattern"

Depending on the version of grep you are using, you can omit pwd. In newer versions . seems to be the default case for grep if no directory is given.

Thus:

grep -rnw -e "pattern"

or

grep -rnw "pattern"

will do the same thing as above!

10
  • 6
    using pwd is not necessary at all, since it is the default. grep -rnw "pattern" suffices.
    – fedorqui
    Commented Dec 2, 2016 at 13:17
  • and in fact the grep -rnw and similar is what was answered like three years ago, I don't see how this answer is adding value.
    – fedorqui
    Commented Dec 2, 2016 at 14:03
  • The selected answer does not show the default pattern, and 5 peoples seemed to have found it useful Commented Dec 14, 2016 at 8:27
  • What do you mean with "default pattern"? The accepted answer contains grep -rnw '/path/to/somewhere/' -e "pattern" which is what you have here. 5 votes after 2.3M visits does not mean that much.
    – fedorqui
    Commented Dec 14, 2016 at 8:45
  • I agree :-) what I was missing in the original answer is the use case that you don't have to give a path at all or to search the current directory recursively which is not reflected in the accepted answer. Thus it was a good learning experience about grep to dig a bit deeper. Commented Dec 14, 2016 at 14:05
39

Try:

find . -name "*.txt" | xargs grep -i "text_pattern"
1
  • 5
    This is actually a prime example of when NOT to use xargs like that .. consider this. echo "file bar.txt has bar" > bar.txt; echo "file foo bar.txt has foo bar" > "foo bar.txt"; echo "You should never see this foo" > foo; find . -name "*.txt" | xargs grep -i foo # ./foo:You should never see this foo . The xargs here matched the WRONG file and did NOT match the intended file. Either use a find .. -print0 | xargs -0 ... but that's a useless use of a pipe or better find ... -exec grep ... {} +
    – shalomb
    Commented Oct 11, 2016 at 20:10
37
grep -lrnw '/root/Desktop/ipozal' -e 'geolocation'

For example:

  • my folder name is "ipozal"
  • it placed on "/root/Desktop"
  • I want to find this text on all files in it "geolocation"
6
  • 5
    Welcome to Stack Overflow! Please consider adding a description or explanation for this code block.
    – jkdev
    Commented Dec 20, 2019 at 0:24
  • 1. backup your folder on desktop
    – Eyni Kave
    Commented Dec 21, 2019 at 13:04
  • 2. my project name is 'ipozal'
    – Eyni Kave
    Commented Dec 21, 2019 at 13:05
  • then use this command and replace 'ipozal' with your folder name, to find files that contains this text 'geolocation'
    – Eyni Kave
    Commented Dec 21, 2019 at 13:06
  • 1
    Good explanation -- you should edit your answer so that the explanation is included.
    – jkdev
    Commented Dec 22, 2019 at 4:14
27

If you strictly want to use find then use find + grep:

find /path/to/somewhere/ -type f -exec grep -nw 'textPattern' {} \;

Steps:

  1. Use find to search files,
  2. Execute grep on all of them.

This gives you the power of find to find files.

  • Use -name Pattern if you want to grep only certain files:

find /path/to/somewhere/ -type f -name \*.cpp -exec grep -nw 'textPattern' {} \;

You can use different options of find to improve your file search.

2
  • What is the difference? Will it work with spaces in the file path? Commented Mar 27, 2020 at 0:59
  • 1
    Does not provide filenames of found files. Commented Dec 8, 2021 at 10:13
27

grep can be used even if we're not looking for a string.

Simply running,

grep -RIl "" .

will print out the path to all text files, i.e. those containing only printable characters.

1
  • 2
    I don't see how this is better than using a mere ls or find (for the recursive)
    – fedorqui
    Commented Dec 2, 2016 at 13:15
26

Silver Searcher is a terrific tool, but ripgrep may be even better.

It works on Linux, Mac and Windows, and was written up on Hacker News a couple of months ago (this has a link to Andrew Gallant's Blog which has a GitHub link):

Ripgrep – A new command line search tool

25

I am fascinated by how simple grep makes it with 'rl':

grep -rl 'pattern_to_find' /path/where/to/find

-r to recursively find a file / directory inside directories..
-l to list files matching the 'pattern'

Use '-r' without 'l' to see the file names followed by text in which the pattern is found!

grep -r 'pattern_to_find' /path/where/to/find

It works just perfect...

2
  • This also works in Git Bash (Windows). Commented Apr 24, 2019 at 15:32
  • But it implies every file must searched (no filter on the file name or file extension level, like .txt). Or is there a way to do that? Commented Apr 24, 2019 at 16:17
24

Here are the several list of commands that can be used to search file.

grep "text string to search” directory-path

grep [option] "text string to search” directory-path

grep -r "text string to search” directory-path

grep -r -H "text string to search” directory-path

egrep -R "word-1|word-2” directory-path

egrep -w -R "word-1|word-2” directory-path
2
24

There is the ack tool that would do exactly what you are looking for:

ack -i search_string folder_path/*

You may ignore -i for case sensitive search.

2
  • 2
    What is this adding to the existing answers? This was suggested more than three years ago already.
    – fedorqui
    Commented Dec 2, 2016 at 13:20
  • 2
    @fedorqui 1)no piping! 2)Use regular expressions 3)Get line numbers, file name with relative path, highlighted text etc. useful for editing after the search e.g "vim +lineno path/file.cpp" will get you right at the line no of interest. See the output of the command "ack include\|hpp" that searches "include" or "hpp" keywords under my search folder and subfolders. I hope the point is clear. Here is the sample output(Can't show the keyword highlights with simple text) process/child.hpp 11:boost/process/child.hpp process/all.hpp 21:#include <boost/process/execute.hpp>
    – Pal
    Commented Jul 11, 2017 at 15:57
23
grep "text-to-find-here" file_name

or

grep "text-to-find-here" directory_path/*

If you want to search the current directory:

grep "text-to-find-here" *
1
  • 8
    Make sure to add an -r switch after grep if you're looking recursively into sub directories. Commented Jun 28, 2021 at 19:28
22

If you are in a Git repository, you can use:

git grep something
3
  • 1
    Out of curiosity, does this only check files that are checked into git and/or not in the .gitignore file? Just checking to be sure because I love how handy this is in most development situations where the directory is already a git repo. Commented Feb 21, 2022 at 20:13
  • 1
    @JoshuaPinter recorded an asciicinema for you asciinema.org/a/g92UTPtL929ysb8umqPj9e2SA the idea is that git grep searchs what's in git, either commited or stashed. When you ignore a file and it's not commited or stashed it's not going to appear in the git grep
    – Dorian
    Commented Feb 23, 2022 at 9:33
  • @Dorian Excellent. Thanks for confirming this thought. That could be a nasty gotcha if you're not aware of it. Thanks again. Commented Feb 23, 2022 at 21:37
22

Expanding the grep a bit to give more information in the output, for example, to get the line number in the file where the text is can be done as follows:

find . -type f -name "*.*" -print0 | xargs --null grep --with-filename --line-number --no-messages --color --ignore-case "searthtext"

And if you have an idea what the file type is you can narrow your search down by specifying file type extensions to search for, in this case .pas OR .dfm files:

find . -type f \( -name "*.pas" -o -name "*.dfm" \) -print0 | xargs --null grep --with-filename --line-number --no-messages --color --ignore-case "searchtext"

Short explanation of the options:

  1. . in the find specifies from the current directory.
  2. -name "*.*" : for all files ( -name "*.pas" -o -name "*.dfm" ) : Only the *.pas OR *.dfm files, OR specified with -o
  3. -type f specifies that you are looking for files
  4. -print0 and --null on the other side of the | (pipe) are the crucial ones, passing the filename from the find to the grep embedded in the xargs, allowing for the passing of filenames WITH spaces in the filenames, allowing grep to treat the path and filename as one string, and not break it up on each space.
2
  • -name '*.*' isn't what you say; it wouldn't pick up on a file called 'file' because the pattern doesn't equate to that (no .ext); * would however (well . files aside). But there's another thing: if you want all files why bother specifying a file name in the first place? No other comment - except that it's nice to know that there still are people who don't use the MS terminology 'folder' (which really after saying it enough I wouldn't add but I wanted to point out the slightly incorrect statement you made with file names - as well as the redundancy/uselessness in the case of 'all').
    – Pryftan
    Commented May 1, 2018 at 23:25
  • print0 ought to be explained as well. Is it for spaces in the file names? Commented Oct 4, 2023 at 21:51
20

A simple find can work handy. alias it in your ~/.bashrc file:

alias ffind find / -type f | xargs grep

Start a new terminal and issue:

ffind 'text-to-find-here'
19
find /path -type f -exec grep -l "string" {} \;

Explanation from comments

find is a command that lets you find files and other objects like directories and links in subdirectories of a given path. If you don't specify a mask that filesnames should meet, it enumerates all directory objects.

-type f specifies that it should proceed only files, not directories etc.
-exec grep specifies that for every found file, it should run grep command, passing its filename as an argument to it, by replacing {} with the filename
19

Try:

find / -type f -exec grep -H 'text-to-find-here' {} \;

which will search all file systems, because / is the root folder.

For home folder use:

find ~/ -type f -exec grep -H 'text-to-find-here' {} \;

For current folder use:

find ./ -type f -exec grep -H 'text-to-find-here' {} \;
3
  • Perhaps the details on differences of folders are obvious to many ...but also very helpful for newbies. +1
    – nilon
    Commented Oct 17, 2016 at 18:07
  • 1
    what is this adding to the existing answers?
    – fedorqui
    Commented Dec 2, 2016 at 13:16
  • Call it my crusade but the word is 'directory'. This isn't Windows (which used to use 'directory' anyway - pre 9x). Please stop saying 'folder'. As for your last command you don't even need the '/' just FYI.
    – Pryftan
    Commented May 1, 2018 at 23:12
18

grep is your good friend to achieve this.

grep -r <text_fo_find> <directory>

If you don't care about the case of the text to find, then use:

grep -ir <text_to_find> <directory>
3
  • In my case it looks like it searches everywhere even if I do specify the directory
    – Pathros
    Commented Mar 20, 2018 at 16:30
  • @Pathros Probably to do with recursion enabled and what directory you specify. Put another way recursion does change things in that way.
    – Pryftan
    Commented May 1, 2018 at 23:38
  • @Pathros Oh and if there are any - s in the search string you'll want to pass in -- to grep first; that can cause interesting side effects otherwise!
    – Pryftan
    Commented Jun 2, 2018 at 0:25
17

To search for the string and output just that line with the search string:

for i in $(find /path/of/target/directory -type f); do grep -i "the string to look for" "$i"; done

e.g.:

for i in $(find /usr/share/applications -type f); \
do grep -i "web browser" "$i"; done

To display filename containing the search string:

for i in $(find /path/of/target/directory -type f); do if grep -i "the string to look for" "$i" > /dev/null; then echo "$i"; fi; done;

e.g.:

for i in $(find /usr/share/applications -type f); \
do if grep -i "web browser" "$i" > /dev/null; then echo "$i"; \
fi; done;
3
  • 2
    I see only downside compared to using find … -exec grep 'str' {} \; (if you have to use find at all).
    – phk
    Commented Oct 7, 2016 at 16:14
  • 2
    This would break horribly if any of the files found by find contained spaces .. you could end up grepping the wrong files and/or missing the right files altogether. Just use find ... -exec grep ... if you have a need to use find .. but in this case a grep -r ... suffices.
    – shalomb
    Commented Oct 11, 2016 at 20:19
  • 2
    what is the point of using a loop over the results of find to then grep? This gets unnecessarily complicated.
    – fedorqui
    Commented Dec 2, 2016 at 13:17
17

I wrote a Python script which does something similar. This is how one should use this script.

./sniff.py path pattern_to_search [file_pattern]

The first argument, path, is the directory in which we will search recursively. The second argument, pattern_to_search, is a regular expression which we want to search in a file. We use the regular expression format defined in the Python re library. In this script, the . also matches newline.

The third argument, file_pattern, is optional. This is another regular expression which works on a filename. Only those files which matches this regular expression will be considered.

For example, if I want to search Python files with the extension py containing Pool( followed by word Adaptor, I do the following,

./sniff.py . "Pool(.*?Adaptor"  .*py
./Demos/snippets/cubeMeshSigNeur.py:146 
./Demos/snippets/testSigNeur.py:259 
./python/moose/multiscale/core/mumbl.py:206 
./Demos/snippets/multiComptSigNeur.py:268 

And voila, it generates the path of matched files and line number at which the match was found. If more than one match was found, then each line number will be appended to the filename.

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