How to find all files containing specific text on Linux?

I'm trying to find a way to scan my entire Linux system for all files containing a specific string of text. Just to clarify, I'm looking for text within the file, not in the file name.

When I was looking up how to do this, I came across this solution twice:

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

However, it doesn't work. It seems to display every single file in the system.

Is this close to the proper way to do it? If not, how should I? This ability to find text strings in files would be extraordinary useful for me for some programming projects I'm doing.

share|improve this question
remember that grep will interpret any . as a single-character wildcard, among others. My advice is to alway use either fgrep or egrep. – Walter Tross Oct 28 '13 at 11:54
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. – Walter Tross Oct 28 '13 at 12:01
reading again your question, it seems like you didn't notice that you should replace the / in your command with a directory of your choice, quite often . – Walter Tross Oct 29 '13 at 13:32
Freak that. Will copy over to the Windows side and use Total Commander :) Tired of this 70-ies ... -gxn --i stuff. – mlvljr Feb 5 '15 at 22:37
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 Jan 28 at 5:16

29 Answers 29

up vote3021down voteaccepted

Do the following:

grep -rnw '/path/to/somewhere/' -e "pattern"
  • -r or -R is recursive,
  • -n is line number, and
  • -w stands match the whole word.
  • -l (lower-case L) can be added to just give the file name of matching files.
  • Along with these, --exclude or --include parameter could be used for efficient searching. Something like below:
grep --include=\*.{c,h} -rnw '/path/to/somewhere/' -e "pattern"

This will only search through the files which have .c or .h extensions. Similarly a sample use of --exclude:

grep --exclude=*.o -rnw '/path/to/somewhere/' -e "pattern"

Above will exclude searching all the files ending with .o extension. Just like exclude file it's possible to exclude/include directories through --exclude-dir and --include-dir parameter; for example, the following shows how to integrate --exclude-dir:

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

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

For more options :

man grep
share|improve this answer
use --exclude. like "grep -rnw --exclude=*.o 'directory' -e "pattern" – rakib Jun 6 '13 at 8:29
I find grep's --include parameter very useful. For example: grep -rnw --include=*.java . -e "whatever I'm looking for" – Lucas A. Nov 14 '13 at 15:43
Is 'directory' a literal value or would that be replaced with something like '/path/to/somewhere'? – Jeff Sep 3 '14 at 18:51
@Jeff directory could be something like '/path/to/somewhere/', with proper permission of-course. – rakib Sep 3 '14 at 20:28
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). – Eliran Malka Mar 24 '15 at 15:09

You can 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.
share|improve this answer
And what does the /* at the end stand for? All directories starting at root? – Nathan Jun 6 '13 at 8:13
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 Jun 6 '13 at 8:14
If you are not searching using a regex you can use fgrep in place of grep on most systems. – markle976 Sep 28 '13 at 14:49
Yes @markle976, in fact from man grep: fgrep is the same as grep -F -> Interpret PATTERN as a list of fixed strings. – fedorqui Sep 30 '13 at 8:23
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 Jan 28 at 12:19

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.


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

share|improve this answer
Very useful, simple and fast. Warning: "On Debian-derived distros, ack is packaged as "ack-grep" because "ack" already existed" (from You may end up running a Kanji code converter on those Linuxes... – Jose_GD Sep 20 '13 at 13:32
ack or ack-grep has nice highlights, but find+grep when proper used is much better in performance – ups Feb 11 '15 at 9:00

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 does not print the file name.

share|improve this answer
Thanx for the find version. My grep version (busybox for NAS) hasn't the -r option, i really needed another solution! – j.c Sep 2 at 10:34

You can use this:

grep -inr "Text" folder/to/be/searched/
share|improve this answer
easiest, verbose, recursive and case insensitive. thumbs up. – Francesco Casula Apr 9 '15 at 12:44
if you add -A3 is even better – albanx Feb 24 at 10:43

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.


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)
share|improve this answer
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 Jan 28 at 5:46
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 Jan 28 at 5:50

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" {} \; 

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. Hope this helps you.

share|improve this answer
OP asked for files that contain the text in their content not filename. – Auxiliary Dec 24 '14 at 3:16


find . -name "*.txt" | xargs grep -i "text_pattern"
share|improve this answer
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 ... {} + – unop Oct 11 at 20:10
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.
share|improve this answer
Can you explain how your answer improves upon the other answers, or how it is sufficiently different from them? – Amos M. Carpenter Feb 26 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 Feb 26 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. – Amos M. Carpenter Feb 26 at 6:35
This is the good answer + the good explanation – KHELILI Hamza Sep 22 at 13:45

If you know the extension of your source files (and the project is not too big), use:

grep "class foo" **/*.c

within the folder of your interest.

The magic here is within using extended globbing (**) which helps you to scan all the files recursively with specific extension. If doesn't work, activate it by shopt -s globstar. You may also use **/*.* for all files (excluding hidden and without extension).

Add the following useful parameters (most common for source code searching):

  • -i - for insensitive searching,
  • -w - to search for a words (in opposite of partial word matching),
  • -n - for showing the line of your match,
  • --context=5 - to increase context, so you recognise surrounding code better,
  • -color - mark up the matching text with color (sometimes it works by default),
  • -I - to ignore binary files (which by specifying file extension, you actually do).

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

share|improve this answer

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
share|improve this answer

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

share|improve this answer


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' {} \;
share|improve this answer
Perhaps the details on differences of folders are obvious to many ...but also very helpful for newbies. +1 – nilon Oct 17 at 18:07
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
share|improve this answer

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


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;


for i in $(find /usr/share/applications -type f); \
do if grep -i "web browser" "$i" > /dev/null; then echo "$i"; \
fi; done;
share|improve this answer
I see only downside compared to using find … -exec grep 'str' {} \; (if you have to use find at all). – phk Oct 7 at 16:14
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. – unop Oct 11 at 20:19

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

./ 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,

./ . "Pool(.*?Adaptor"  .*py

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.

share|improve this answer

Hope this is of assistance..

Expanding the grep a bit to give more info in the output, eg 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.
share|improve this answer

The below command will work fine for this approach:

find ./ -name "file_pattern_name"  -exec grep -r "pattern" {} \;
share|improve this answer
what is the point of using find and then grep -r? They are meant for the same, so this is redundant. – fedorqui Dec 23 '15 at 17:02
ohh!! corrected , Actually find is for running grep on filtered files and not all, thanks – Pradeep Goswami Dec 30 '15 at 15:25

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

grep -rnw `pwd` -e "pattern"
share|improve this answer

If you have a set of files that you will always be checking you can alias their paths, for example:

alias fd='find . -type f -regex ".*\.\(inc\|info\|module\|php\|test\|install\|uninstall\)"'

Then you can simply filter the list like this:

grep -U -l $'\015' $(fd)

Which filters out the list fd to files that contain the CR pattern.

I find that aliasing the files that I am interested in helps me create easier scripts then always trying to remember how to get all those files. The recursive stuff works as well but sooner or later you are going to have to contend with weeding out specific file types. Which is is why I just find all the file types I'm interested in to begin with.

share|improve this answer

Avoid the hassle and install ack-grep. It eliminates a lot of permission and quotation issues.

apt-get install ack-grep

Then go to the directory you want to search and run the command below

cd /
ack-grep "find my keyword"
share|improve this answer

Try this

find . -type f -name some_file_name.xml -exec grep -H PUT_YOUR_STRING_HERE {} \;
share|improve this answer
This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. - From Review – Sergey Denisov Nov 18 '15 at 20:14
@SergeyDenisov What gives? This is definitely an answer. (Whether it works or not is another matter.) – jpaugh Nov 18 '15 at 23:43
@jpaugh then you should explain it in details. – Sergey Denisov Nov 18 '15 at 23:55
@SergeyDenisov. It gives a suggested course of action that might produce the correct result. Or, even if it does not, it might help someone else. That's what I mean by, "It's an answer." If you want to know how it works, ask the poster. – jpaugh Nov 18 '15 at 23:58
@jpaugh I'm sure that one line command/code is not enough for a complete answer. You could write a comment giving a suggested course of action, but an answer should include an explanation. That's why this answer was flagged as "Low Quality Post" (not by me). – Sergey Denisov Nov 19 '15 at 9:47

try this

find . | xargs grep 'word' -sl
share|improve this answer
this is far slower than the grep solution – amine Dec 22 '14 at 16:58

I came across this solution twice:

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


Is this close to the proper way to do it?

Short answer: Yes, it is very close.

Long answer: This command is correct.

Using just grep -r (grep --recursive) is more straightforward:

grep 'text-to-find-here' -r <path_to_search>

However, your command (combining find and grep) comes in handy sometimes, for example on systems where the grep command doesn't support -r (--recursive), so let's examine the rest of the question:

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


However, it doesn't work. It seems to display every single file in the system.

You probably get error messages such as

grep: '<name_of_file_you_do_have_access_to>': Permission denied

You can avoid these by adding option -s (or --no-messages) to grep.

But then you still get errors like

find: '<name_of_file_you_do_have_access_to>': Permission denied

To avoid this, you can add 2>/dev/null at the end of your command, to discard all error messages, which gives:

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

share|improve this answer

You can use the below command as you don't want a file name, but you want to search from all the files. Here are I am capturing "TEXT" from all the log files, making sure that the file name is not printed:

# grep -e TEXT *.log | cut -d' ' --complement -s -f1

Using grep with the -e option is quite quick compared to other options as it is for a PATTERN match.

share|improve this answer

Try this -

find / -type f -name "*" -exec grep -il "String_to_search" {} \;


for i in /*;do grep -Ril "String_to_search" $i;done 2> /dev/null
share|improve this answer

Looks like all that is needed is 2>/dev/null to remove unwanted error output

find / -type f -exec grep -H 'text-to-find-here' {} \; 2>/dev/null
share|improve this answer

There is an "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

share|improve this answer

grep -Erni + "text you wanna search"

The command will search recursivly in all files and directories of the current directory and print the result.

Note: if your grep output isn't colored, you can change it by using the grep='grep --color=always' alias in your shell src file

share|improve this answer

protected by durron597 Aug 6 '15 at 19:34

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

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