grep use - How do I find all files containing specific text on Linux?




shell command (25)

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 extraordinarily useful for some programming projects I'm doing.


Answers

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.


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.


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)

There is an ack tool that would do exactly what you are looking for.

http://linux.die.net/man/1/ack

ack -i search_string folder_path/*

You may ignore -i for case sensitive search


Try:

find . -name "*.txt" | xargs grep -i "text_pattern"

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.


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


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.

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>

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 -ia "Search query"

And it will do the task for you!


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"

The below command will work fine for this approach:

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

Do the following:

grep -rnw '/path/to/somewhere/' -e 'pattern'
  • -r or -R is recursive,
  • -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.

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 a particular directory(ies) through --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/somewhere/' -e "pattern"
    

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

For more options check man grep.


Try this:

find . | xargs grep 'word' -sl

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 the common parameters such as:

  • -i - Insensitive searching.
  • -I - Ignore the binary files.
  • -w - Search for the whole words (in 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.

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


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


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

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

-r to find recursively 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

Works just perfect..

Hope it helps!


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;

Hope this is of assistance...

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.

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

You can use this:

grep -inr "Text" folder/to/be/searched/

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

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.

Hope this helps you.


grep 2.5.3 introduced the --exclude-dir parameter which will work the way you want.

grep -rI --exclude-dir=\.svn PATTERN .

You can also set an environment variable: GREP_OPTIONS="--exclude-dir=.svn"

I'll second Andy's vote for ack though, it's the best.





linux text grep directory find