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' {} \; 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.-e is the pattern used during the searchAlong 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.
r option is lazy (traverses depth-first, than stops after the first directory), while R is greedy (will traverse the entire tree correctly).-I option to skip all binary files.-r and -R seems to itself differ between different grep implementations. The manpage for the GNU grep I have on Ubuntu seems to say that the only difference is that -R follows symlinks and -r does not (perhaps there were symlinks to folders in the folder you were testing in when you commented in 2015, explaining the behaviour you reported then?), but based on a look at a BSD grep manpage, I think -R, -r, and --recursive are all equivalent in BSD grep. (The POSIX standard, meanwhile, doesn't require any of those flags to exist at all!)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.-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.grep -Ril "text-to-find-here" ~/sites/ or use . for current directory grep -Ril "text-to-find-here" .grep -ril "name" /, but uppercase R didn't work.grep --color=never can increase search speed.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.
There is also The Silver Searcher, which is like ack, but 3-5 times faster than it and even ignores patterns from a .gitignore file.
ag 'what I want' ./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
max-depth option for find this is the only way to execute this kind of search while setting a max-depth from the starting locationRecursive and case insensitive grep with line numbers:
grep -inr "Text" folder/to/be/searched/ 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.
ripgrepIf 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.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" {} \; 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$ 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.
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-iname is case-insensitive which means it would also find .TXT files, for example, as well as TxT and TXt and so on.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"
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)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.find … -exec grep … +. If you insist on using find together with xargs, use -print0 and -0.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!
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.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:
RipGrep - fastest search tool around:
rg 'text-to-find-here' / -l 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...
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!
pwd is not necessary at all, since it is the default. grep -rnw "pattern" suffices.grep -rnw and similar is what was answered like three years ago, I don't see how this answer is adding value.grep -rnw '/path/to/somewhere/' -e "pattern" which is what you have here. 5 votes after 2.3M visits does not mean that much.Try:
find . -name "*.txt" | xargs grep -i "text_pattern" 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 ... {} +grep -lrnw '/root/Desktop/ipozal' -e 'geolocation' For example:
If you strictly want to use find then use find + grep:
find /path/to/somewhere/ -type f -exec grep -nw 'textPattern' {} \;
Steps:
find to search files,grep on all of them.This gives you the power of find to find files.
-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.
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.
ls or find (for the recursive)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):
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...
.txt). Or is there a way to do that?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 egrep is equivalent to grep -E and it means --extended-regexp you can find details here unix.stackexchange.com/a/17951/196072There 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.
If you are in a Git repository, you can use:
git grep something 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.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" * -r switch after grep if you're looking recursively into sub directories.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:
. in the find specifies from the current directory.-name "*.*" : for all files ( -name "*.pas" -o -name "*.dfm" ) : Only the *.pas OR *.dfm files, OR specified with -o -type f specifies that you are looking for files-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.-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').print0 ought to be explained as well. Is it for spaces in the file names?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 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' {} \; Try this command. Which will give you the files containing the pattern you entered.
sudo grep -inr "your-pattern" / Here: i - Ignore case distinctions, so that characters that differ only in case match each other.
n - Make sure that the first character of actual line content lies on a tab stop, so that the alignment of tabs looks normal.
r - Read all files under each directory, recursively, following symbolic links only if they are on the command line. Note that if no file operand is given, grep searches the working directory.
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> - s in the search string you'll want to pass in -- to grep first; that can cause interesting side effects otherwise!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; find … -exec grep 'str' {} \; (if you have to use find at all).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.
.as a single-character wildcard, among others. My advice is to alway use either fgrep or egrep.-Hwith-l(and maybegrepwithfgrep). To exclude files with certain patterns of names you would usefindin a more advanced way. It's worthwile to learn to usefind, though. Justman find.find … -exec <cmd> +is easier to type and faster thanfind … -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.