Reputation: 78499
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' {} \;
Upvotes: 7645
Views: 11668841
Reputation: 41
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 symlinks 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:
Various special characters in bash have to be escaped.
Grep searches for a regex which has to be escaped.
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 embarrasingly 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:
running bash pipe commands in background with & ampersand
How do I exclude a directory when using `find`? (most answers were wrong and I had to fix it for modern find).
https://unix.stackexchange.com/questions/172481/how-to-quote-arguments-with-xargs
https://unix.stackexchange.com/questions/538631/multi-threaded-find-exec
Upvotes: 1
Reputation: 142775
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
.
Upvotes: 13878
Reputation: 207
You can also use awk
:
awk '/^(pattern)/{print}' /path/to/find/*
pattern
is the string you want to match in the files.
Upvotes: 2
Reputation: 392
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.
Upvotes: 18
Reputation: 274
See also The Platinium Searcher, which is similar to The Silver Searcher and it's written in Go.
Example:
pt -e 'text to search'
Upvotes: 9
Reputation: 8417
find
with xarg
s 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
Upvotes: 14
Reputation: 386
You can use the following commands to find particular text from a file:
cat file | grep 'abc' | cut -d':' -f2
Upvotes: 10
Reputation: 33607
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.
Upvotes: 10
Reputation: 317
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.
Upvotes: 11
Reputation: 3147
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
Upvotes: 16
Reputation: 5422
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"
Upvotes: 15
Reputation: 822
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
Upvotes: 16
Reputation: 4920
A simple find
can work handy. alias it in your ~/.bashrc
file:
alias ffind find / -type f | xargs grep
Start a new terminal and issue:
ffind 'text-to-find-here'
Upvotes: 20
Reputation: 475
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" *
Upvotes: 24
Reputation: 1467
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...
Upvotes: 26
Reputation: 39516
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.
Upvotes: 27
Reputation: 1530
grep -lrnw '/root/Desktop/ipozal' -e 'geolocation'
For example:
Upvotes: 38
Reputation: 11033
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!
Upvotes: 53
Reputation: 2899
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...
Upvotes: 53
Reputation: 840
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.Upvotes: 57
Reputation: 957
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!
Upvotes: 59
Reputation: 166795
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 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
.Upvotes: 142
Reputation: 2803
Recursive and case insensitive grep with line numbers:
grep -inr "Text" folder/to/be/searched/
Upvotes: 170
Reputation: 4101
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
Upvotes: 312
Reputation: 16769
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.
Upvotes: 475
Reputation: 290215
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.Upvotes: 2355
Reputation: 12002
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
.
Upvotes: 10
Reputation: 3146
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
Upvotes: 10