7706
votes

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
  • 47
    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
  • 16
    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
  • 13
    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. Commented Jan 28, 2016 at 5:16
  • 4
    Does this answer your question? How can I use grep to find a word inside a folder? 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, 2024 at 19:17

57 Answers 57

1
2
17
votes

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.

Sign up to request clarification or add additional context in comments.

Comments

17
votes

All previous answers suggest grep and find. But there is another way: Use Midnight Commander

It is a free utility (30 years old, proven by time) which is visual without being GUI. It has tons of functions, and finding files is just one of them.

1 Comment

ranger would be in the same idea
16
votes

The below command will work fine for this approach:

find ./ -name "file_pattern_name"  -exec grep -r "pattern" {} \;

3 Comments

what is the point of using find and then grep -r? They are meant for the same, so this is redundant.
ohh!! corrected , Actually find is for running grep on filtered files and not all, thanks
still, this does not make any sense, you can filter with find.
16
votes

Use:

grep -c Your_Pattern *

This will report how many copies of your pattern are there in each of the files in the current directory.

Comments

16
votes

I tried the grep command below. It helps searching contents within my repository at /etc/yum.repos.d.

grep -Ril -e 'texttoSearch' /etc/yum.repos.d

1 Comment

It outputs files, but doesn't count them
16
votes

Try this:

find . | xargs grep 'word' -sl

2 Comments

this is far slower than the grep solution
@amine Yeah rather than using grep directly it pipes all the files find finds to xargs running grep on it. I'm sure you understand that but just to add to those who might not. The command here is .. I can't atm think of a good analogy but it's adding a lot of unnecessary and harmless overhead.
16
votes

Try this:

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

Or

for i in /*;do grep -Ril "String_to_search" $i;done 2> /dev/null

4 Comments

what is this adding to the existing answers?
Good Question - Let start with top answers to this question. I tried below commands on AIX server with more than 15k files in log dir. grep -rnw '/path/to/somewhere/' -e "pattern" >>> got the error "/usr/bin/grep: 0403-027 The parameter list is too long." grep -Ril "text-to-find-here" / >>> got the error "/usr/bin/grep: 0403-027 The parameter list is too long." ack 'text-to-find-here' >>> got the error "Segmentation fault(coredump)"
find / -type f -name "" -exec grep -il "String_to_search" {} \; >>> It will produce the result with filename and file data. find / -type f -exec grep -H 'text-to-find-here' {} \; >>> It will produce the result with filename only. for i in /;do grep -Ril "String_to_search" $i;done 2> /dev/null >>> It will work like grep -Ril "text-to-find-here" / but support large number of file.
@VIPINKUMAR The parameter list is too long. Yeah that's what xargs is for. Unsure on AIX if it has that though; no comment on your actual commands.
15
votes

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

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

grep with -e option is quite quick compared to other option as it is for PATTERN match

2 Comments

Personally I think you should remove the # because other than comments that typically implies something - and you shouldn't be root unless you absolutely have to be. Even so you needn't have the prompt surely? Call this petty but I have seen people many times over the years simply copy and paste and do things without truly understanding it. Not saying any will here but still.. Just a thought.
Better way use find + grep stackoverflow.com/a/51023211/7918560
15
votes

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"

2 Comments

Can you add the presumptions to the answer? On Ubuntu/Debian? What distribution and version was this tested on? Ubuntu 16.04 (Xenial Xerus)?
@PeterMortensen ack-grep is available on any Linux disruption. All versions perform this basic functionality.
14
votes

find with xargs is preferred when there are many potential matches to sift through. It runs more slowly than other options, but it always works. As some have discovered,xargs does not handle files with embedded spaces by default. You can overcome this by specifying the -d option.

Here is @RobEarl's answer, enhanced so it handles files with spaces:

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

Here is @venkat's answer, similarly enhanced:

find . -name "*.txt" | xargs -d '\n' grep -i "text_pattern"

Here is @Gert van Biljon's answer, similarly enhanced:

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

Here is @LetalProgrammer's answer, similarly enhanced:

alias ffind find / -type f | xargs -d '\n' grep

Here is @Tayab Hussain's answer, similarly enhanced:

find . | xargs -d '\n' grep 'word' -sl

3 Comments

So grep -rl doesn't work with many matches?
"under many other Unix-like systems, arbitrarily long lists of parameters cannot be passed to a command, so the command may fail with an error message of "Argument list too long" (meaning that the exec system call's limit on the length of a command line was exceeded)" ... en.wikipedia.org/wiki/Xargs
"--with-filename" is great, I do not know that, thanks a lot!
11
votes

Use:

grep -Erni + "text you wanna search"

The command will search recursively 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 source file.

1 Comment

You might want to point out that -i makes the search case-insensitive; by default it doesn't have that - nor should it as Unix (etc.) isn't a case-insensitive OS. You might also want to specify what the other options are for too.
10
votes

My use case was to find Python code I had written way back that wrote jsonlines a particular way. I knew that jsonl would be part of the function name and to_json would appear in the body, but not much else.

Despite 50 answers, finding more than one string in the same file (whether or not in the same line) hasn't been answered.

The -q in grep is for quiet. Nothing is printed, only the return value is set. Thus the -print at the end. Each -exec only runs if the previous one succeeded. So if you have many files it pays to think about patterns that will eliminate files you aren't interested in.

find . -type f -name "*.py" \
  -exec grep -q -e 'to_json' {} \; \
  -exec grep -q -e 'def\s.*jsonl' {} \; \
  -print

1 Comment

Adding a small note for anybody passing by (and ignoring this like me in first instance): the space between \; is necessary or it will not work
10
votes

You can use ripgrep which will respect the default project's .gitignore file.

$ rg fast README.md
75:  faster than both. (N.B. It is not, strictly speaking, a "drop-in" replacement
88:  color and full Unicode support. Unlike GNU grep, ripgrep stays fast while
119:### Is it really faster than everything else?
124:Summarizing, ripgrep is `fast` because:
129:  optimizations to make searching very fast.

where fast keyword is highlighted in the terminal.

To suppress Permission denied errors:

$ rg -i rustacean 2> /dev/null

Which will redirect the standard error (stderr) output to /dev/null.

2 Comments

Re "...respect the default project's .gitignore file": Can you provide a more complete description? 1) It presumably does more than that, like ignoring the content of the .git directory. 2) Must the search be done from the Git repository root folder? 3) What happens if not? Does it work like normal grep if outside a Git repository? (But without "Edit:", "Update:", or similar - the answer should appear as if it was written today.)
Please also review Why not upload images of code/errors when asking a question? (e.g., "Images should only be used to illustrate problems that can't be made clear in any other way, such as to provide screenshots of a user interface."). It covers answers as well.
10
votes

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.

Comments

9
votes

Try this

find . -type f -name some_file_name.xml -exec grep -H PUT_YOUR_STRING_HERE {} \;

8 Comments

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
@SergeyDenisov What gives? This is definitely an answer. (Whether it works or not is another matter.)
@jpaugh then you should explain it in details.
@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 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).
|
9
votes

As Peter in the previous answer mentioned, all previous answers suggest grep and find.

But there is a more sophisticated way using Gnome Commander with a perfect GUI and with tons of options since 2001, and finding files is just one of them. It is a free utility as well, proven by time.

Comments

9
votes

GUI Search Alternative - For Desktop Use:

- As the question is not precisely asking for commands

Searchmonkey: Advanced file search tool without having to index your system using regular expressions. Graphical equivalent to find/grep. Available for Linux (Gnome/KDE/Java) and Windows (Java) - open source GPL v3

Features:

  • Advanced Regular Expressions
  • Results shown in-context
  • Search containing text
  • Panel to display line containing text
  • New 2018 updates
  • etc.

Download - Links:

.

Screen-shot:

Enter image description here

Comments

9
votes

You can use the following commands to find particular text from a file:

cat file | grep 'abc' | cut -d':' -f2

2 Comments

the question is about finding which files contain a string, not about finding a string in a file.
And in any case this is a useless use of cat... porkmail.org/era/unix/award.html
9
votes

See also The Platinium Searcher, which is similar to The Silver Searcher and it's written in Go.

Example:

pt -e 'text to search'

1 Comment

A link to a solution is welcome, but please ensure your answer is useful without it: add context around the link so your fellow users will have some idea what it is and why it’s there, then quote the most relevant part of the page you're linking to in case the target page is unavailable. Answers that are little more than a link may be deleted.
8
votes

I'm trying to find a way to scan my entire Linux system for all files containing a specific string of text. ... 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 extraordinarily useful for some programming projects I'm doing.

While you should never replace (or alias) a system command with a different program, due to risk of mysterious breakage of scripts or other utilities, if you are running a text search manually or from your own scripts or programs you should consider the fastest suitable program when searching a large number of files a number of times. Ten minutes to half an hour time spent installing and familiarizing yourself with a better utility can be recovered after a few uses for the use-case you described.

A webpage offering a "Feature comparison of ack, ag, git-grep, GNU grep and ripgrep" can assist you to decide which program offers the features you need.

  • Andrew Gallant's Blog claims: "ripgrep is faster than {grep, ag, git grep, ucg, pt, sift}" (a claim shared by some of the others, this is why a feature comparison is helpful). Of particular interest is his section on regex implementations and pitfalls.

    The following command searches all files, including hidden and executable:

    $ rg -uuu foobar

  • The Silver Searcher (ag) claims it is 5-10x faster than Ack. This program is suggested in some other answers. The GitHub doesn't appear as recent as ripgrep's and there are noticably more commits and branches with fewer releases, it's hard to draw an absolute claim based on those stats. The short version: ripgrep is faster, but there's a tiny learning curve to not get caught by the differences.

  • So what could be next, you guessed it, the platinum searcher. The claims are: it searches code about 3–5× faster than ack, but its speed is equal to the silver searcher. It's written in GoLang and searches UTF-8, EUC-JP and Shift_JIS files; if that's of greater interest. The GitHub is neither particularly recent or active. GoLang itself has a fast and robust regex, but the platinum searcher would be better recommended if it had a better user interest.

For a combination of speed and power indexed query languages such as ElasticSearch or Solr can be a long term investment that pays off, but not if you want a quick and simple replacement for grep. OTOH both have an API which can be called from any program you write, adding powerful searches to your program.

While it's possible to spawn an external program, execute a search, intercept its output and process it, calling an API is the way to go for power and performance.

This question was protected Aug 6 '15 at 19:34 with this caution:
  We're looking for long answers that provide some explanation and context. Don't just give a one-line answer; explain why your answer is right, ideally with citations.

While some answers suggest alternative ways to accomplish a search they don't explain why other than it's "free", "faster", "more sophisticated", "tons of features", etc. Don't try to sell it, just tell us "why your answer is right". I've attempted to teach how to choose what's best for the user, and why. This is why I offer yet another answer, when there are already so many. Otherwise I'd agree that there are already quite a few answers; I hope I've brought a lot new to the table.

Comments

5
votes

Your command is correct. You just need to add -l to grep:

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

Comments

4
votes

Kindly customize the below command according to demand and find any string recursively from files.

grep -i hack $(find /etc/ -type f)

3 Comments

Customise what parts? Your answer needs more explanation (see @rakib_'s answer for an example)
customise means choose "hack"(searching string) keyword and /etc location according to your demand. you can also use below command grep -ErIRi hack /*
This fails if a file name contains spaces.
4
votes

I think it is worth mentioning how you can find:

All files containing at least one text, among a big set of texts:

grep -rlf ../patternsFile.txt .

Output:

./file1
./file2
./file4

The above, grouped by each text:

cat ../patternsFile.txt | xargs -I{} sh -c "echo {}; grep -rl \"{}\" ."

Output:

pattern1
./file1
./file2
pattern2
./file1
./file4
pattern3
./file1
./file2
./file4

Note that in order not to match patternsFile.txt itself, you need to add it one directory up (as shown in the above examples).

Comments

3
votes

Go to the directory. For search, then search your text by -> grep -r "yoursearchtext"

Now you should see all files which has matching text.

Then go to file → less fileName

Then read the file's full text → Shift + G

Then search the text in the file → ?+yousearchText

Then search all matching case → Ctrl + N

Comments

2
votes

You can also use awk:

awk '/^(pattern)/{print}' /path/to/find/*

pattern is the string you want to match in the files.

2 Comments

Does this traverse a directory tree, or only the files in the path specified without going into contained directories?
Doesn't work for me: user@host:/dir$ awk '/^(getCookie)/{print}' . awk: warning: command line argument .' is a directory: skipped`
1
vote

After checking the alternatives for a desktop, I wrote an open-source GUI program for full text search. It's blazing fast in comparison with grep flavors.

You can check it at Missing Linux GUI app to full-text search files. It can search for both content and file names in a intuitive search string, so you can look for "license mit *.md" and get few false positives ;)

2 Comments

What kind of desktop? What is it based on? What was it tested on? What are the dependencies for it to run? What Linux flavours does it work on? What Linux flavours does it not work on?
We use it at Ubuntu 22.04 and 23.04, also it got some testing under windows by one enthusiast. It is written using compose for desktop (native graphics and kotlin logick) so should work on all falvours, I'll greatly appreciate any reports. I use it daily and plan to add indexing external archive volumes with offline search (u23.04). It is expected to run with no deps being packed together in a big .deb package.
1
vote

The offered solutions could be better quality. There are a number of unsolved issues with the given answers:

  • If you don't know where to look, then searching the entire filesystem isn't as trivial as specifying the root directory on Linux. There's some stuff to exclude. What?

  • Following symbolic links can lead to loops which means the search never terminates and never investigates some of the files on the disk.

  • In most cases, you do not want to search inside virtual directories, like /dev/, /proc/ and /sys/, because that will spew errors, and not search actual files on disk, instead searching program memory and raw device data, causing the search to take very, very long.

  • You probably also don't want to search in /tmp/, which is usually a memory-mounted filesystem that is purged upon reboot and automatically cleaned on modern Linuxes.

  • The terminal has a limited capacity for text. If this is exceeded, results are lost. Results should be put in a file.

  • If the terminal connection drops at any point in the search, results are lost and everything has to be restarted. Running in the background would be much preferred.

  • Searching for code, with all the examples, is still very tricky on the command line. In particular: Escaping stuff. In particular:

  1. Various special characters in bash have to be escaped.

  2. Grep searches for a regex which has to be escaped.

  3. If commands are put into other commands, that leads to more things being escaped.

All three combined when searching code is a literal nightmare to figure out: the user should have an input for what to search for that does not require any escaping.

  • Filenames can have special characters in them, mucking with your search. The command should be able to deal with evil filenames with quotes and spaces and newlines and other shenanigans in them.

  • Files could be removed or changed while you're searching, leading to 'File not Found' errors cluttering the output. You could not have permission to things, also cluttering the output. Including an option to suppress errors helps.

  • Most of the examples use only a single thread, making them unnecessarily dreadfully slow on modern many-core servers, even though the task is embarrassingly parallel. The search command should start one thread per CPU core to keep it busy.

The following should be a big improvement:

# Note: Change search string below here.
nCores=$(nproc --all)
read -r -d '' sSearch <<'EOF'
echo $locale["timezone"]." ".$locale['offset'].PHP_EOL;
EOF
find -print0 \(  -type f \) -and \( -not \( -type l \) \) -and \( -not \( -path "./proc/*" -o -path "./sys/*" -o -path "./tmp/*"  -o -path "./dev/*" \) \) | xargs -P $nCores -0 grep -Fs "$sSearch" | tee /home/npr/results.txt &

If you do not want to suppress grep errors, use this:

# Note: Change search string below here.
nCores=$(nproc --all)
read -r -d '' sSearch <<'EOF'
echo $locale["timezone"]." ".$locale['offset'].PHP_EOL;
EOF
find -print0 \(  -type f \) -and \( -not \( -type l \) \) -and \( -not \( -path "./proc/*" -o -path "./sys/*" -o -path "./tmp/*"  -o -path "./dev/*" \) \) | xargs -P $nCores -0 grep -F "$sSearch" | tee /home/npr/results.txt &

Change EOF to any other A-Za-z variable if it's desired to search for the literal text EOF.

With this, I reduced a day-long search that had thousands of errors resulting from several of the top answers here into an easy sub 1-minute command.


Reference:

Also see these answers:

Comments

1
2

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.