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. Answers that don't include explanations may be removed.

15

remember that grep will interpret any . as a single-character wildcard, among others. My advice is to alway use either fgrep or egrep.
– Walter TrossOct 28 '13 at 11:54

8

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 TrossOct 28 '13 at 12:01

4

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.
– hagelloJan 28 '16 at 5:16

To search non-recursively in a given path the command is `grep --include=*.txt -snw "pattern" thepath/*.
– Stéphane LaurentAug 15 '16 at 12:34

@StéphaneLaurent I think you are complicating it too much. Just say grep "pattern" path/*.txt
– fedorquiDec 2 '16 at 13: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.
– fedorquiJun 6 '13 at 8:14

2

Yes, /* stands for that. Anyway I just tested it and noticed that just / works.
– fedorquiJun 6 '13 at 8:15

9

If you are not searching using a regex you can use fgrep in place of grep on most systems.
– markle976Sep 28 '13 at 14:49

7

Yes @markle976, in fact from man grep: fgrep is the same as grep -F -> Interpret PATTERN as a list of fixed strings.
– fedorquiSep 30 '13 at 8:23

14

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" .
– BlackJan 28 '16 at 12:19

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_GDSep 20 '13 at 13:32

7

ack or ack-grep has nice highlights, but find+grep when proper used is much better in performance
– Sławomir LenartFeb 11 '15 at 9:00

Thanx for the find version. My grep version (busybox for NAS) hasn't the -r option, i really needed another solution!
– j.cSep 2 '16 at 10:34

3

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.
– mightypileAug 16 '17 at 15:10

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

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
– MeneApr 20 '17 at 13:46

1

@Auxiliary - included a sample output to avoid any confusion for the readers.
– lkamalOct 7 '17 at 5:56

2

@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.
– PryftanMay 1 '18 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.
– PryftanMay 1 '18 at 23:04

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.
– hagelloJan 28 '16 at 5:46

3

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.
– hagelloJan 28 '16 at 5:50

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:

It's much quicker than any other tool like GNU/BSDgrep, 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.

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.Nov 30 '17 at 6:47

Can you explain how your answer improves upon the other answers, or how it is sufficiently different from them?
– Amos M. CarpenterFeb 26 '16 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).
– enfinetFeb 26 '16 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. CarpenterFeb 26 '16 at 6:35

This is the good answer + the good explanation
– khelili milianaSep 22 '16 at 13:45

6

@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".
– leetNightshadeFeb 20 '17 at 5:58

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 ... {} +
– shalombOct 11 '16 at 20:10

using pwd is not necessary at all, since it is the default. grep -rnw "pattern" suffices.
– fedorquiDec 2 '16 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.
– fedorquiDec 2 '16 at 14:03

The selected answer does not show the default pattern, and 5 peoples seemed to have found it useful
– mahatmanichDec 14 '16 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.
– fedorquiDec 14 '16 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.
– mahatmanichDec 14 '16 at 14:05

Faster and easier alternatives

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

'find is the standard tool for searching files containing specific text on Unix-like platforms' seems rather ambiguous to me. Even besides recursive grepfind doesn't directly search the inside of files for text. And maybe those additional tools are useful to some but old timers and those whoa are well accustomed to e.g. grep wouldn't give them any time at all (well I certainly won't). Not saying they're useless though.
– PryftanMay 1 '18 at 23:36

"....containing specific text..." : this part of the sentence was not accurate (because it's not find itself that deals with this part of the search). Edited. Thanks.
– BludzeeJun 1 '18 at 9:21

Glad to be of help! The only thing else at a very very quick glance is changing the word folder to directory but I know that’s a crusade of mine I will never win completely. Not giving up though...
– PryftanJun 1 '18 at 16:13

Perhaps the details on differences of folders are obvious to many ...but also very helpful for newbies. +1
– nilonOct 17 '16 at 18:07

1

what is this adding to the existing answers?
– fedorquiDec 2 '16 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.
– PryftanMay 1 '18 at 23:12

-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').
– PryftanMay 1 '18 at 23:25

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

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 Pythonre 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,

I see only downside compared to using find … -exec grep 'str' {} \; (if you have to use find at all).
– phkOct 7 '16 at 16:14

1

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.
– shalombOct 11 '16 at 20:19

1

what is the point of using a loop over the results of find to then grep? This gets unnecessarily complicated.
– fedorquiDec 2 '16 at 13:17

What is this adding to the existing answers? This was suggested more than three years ago already.
– fedorquiDec 2 '16 at 13:20

1

@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>
– PalJul 11 '17 at 15:57

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.
– PryftanJun 2 '18 at 1:30

@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.
– PryftanJun 2 '18 at 1: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).