I'm working on a script to grep
certain directories:
{ grep -r -i CP_Image ~/path1/;
grep -r -i CP_Image ~/path2/;
grep -r -i CP_Image ~/path3/;
grep -r -i CP_Image ~/path4/;
grep -r -i CP_Image ~/path5/; }
| mailx -s GREP email@domain.example
How can I limit results only to extensions .h
and .cpp
?
grep -r -i CP_Image ~/path1/*.{h,cpp}
?
ag -i CP_Image ~/path[1-5] | mailx -s GREP email@domain.com
. Job done.
-r
to grep
to have it search for files as that breaks the UNIX mantra of having tools that "do one thing and do it well". There's a perfectly good tool for finding files with a VERY obvious name.
Just use the --include
parameter, like this:
grep -inr --include \*.h --include \*.cpp CP_Image ~/path[12345] | mailx -s GREP email@domain.example
That should do what you want.
To take the explanation from HoldOffHunger's answer below:
grep: command
-r: recursively
-i: ignore-case
-n: each output line is preceded by its relative line number in the file
--include \*.cpp: all *.cpp: C++ files (escape with \ just in case you have a directory with asterisks in the filenames)
./: Start at current directory.
Some of these answers seemed too syntax-heavy, or they produced issues on my Debian Server. This worked perfectly for me:
grep -r --include=\*.txt 'searchterm' ./
...or case-insensitive version...
grep -r -i --include=\*.txt 'searchterm' ./
grep: command
-r: recursively
-i: ignore-case
--include: all *.txt: text files (escape with \ just in case you have a directory with asterisks in the filenames)
'searchterm': What to search
./: Start at current directory.
Source: PHP Revolution: How to Grep files in Linux, but only certain file extensions?
*
using \*.cpp
or '*.cpp'
. Otherwise it won’t give the expected result when the working directory contains some *.txt
files.
--include=<pattern>
but it is important to escape *
with --include <pattern>
(a space instead of =
) which feels very similar otherwise.
--include=<pattern>
. It also works with --include<pattern>
, so long as there are no files matching the pattern in the current directory. I.e., it's safest to escape the pattern when you're not using the =
syntax, but you can live dangerously if you assume there are no files matching the pattern in the current directory.
grep -rnw "some thing to grep" --include=*.{module,inc,php,js,css,html,htm} ./
--include
option after needle, not with other options?
--
?
--include=*.foo
. The working solution was wrapping the --include
value in quotes. E.g. --include="*.foo"
.
Use:
find . -name '*.h' -o -name '*.cpp' -exec grep "CP_Image" {} \; -print
-name
arguments. strange things can happen if you don't. find . \( -name '*.h' -o -name '*.cpp' \) -exec grep "CP_Image" {} \; -print
find
can optionally bundle arguments, reducing invocations of the called process to a minimum. find . \( -name \*.h -o -name \*.cpp \) -exec grep -H CP_Image {} +
This is suggested but not highlighted in @fedorqui's answer below and is a worthwhile improvement. The -H
argument to grep here is useful when find only identifies a single matching file. This could eliminate the usage of -print
in the answer. If your total list of files is sufficiently small, using a recursive shell glob (eg. {path1,path2}/**/*.{cpp,h}
) might be preferable.
There isn't any -r
option on HP and Sun servers, but this way worked for me on my HP server:
find . -name "*.c" | xargs grep -i "my great text"
-i
is for case insensitive search of string.
ll
but does not add --color=auto
to grep.
This answer is good:
grep -r -i --include \*.h --include \*.cpp CP_Image ~/path[12345] | mailx -s GREP email@domain.example
But it can be updated to:
grep -r -i --include \*.{h,cpp} CP_Image ~/path[12345] | mailx -s GREP email@domain.example
Which can be simpler.
Since this is a matter of finding files, let's use find
!
Using GNU find you can use the -regex
option to find those files in the tree of directories whose extension is either .h
or .cpp
:
find -type f -regex ".*\.\(h\|cpp\)"
# ^^^^^^^^^^^^^^^^^^^^^^^
Then, it is just a matter of executing grep
on each of its results:
find -type f -regex ".*\.\(h\|cpp\)" -exec grep "your pattern" {} +
If you don't have this distribution of find you have to use an approach like Amir Afghani's, using -o
to concatenate options (the name is either ending with .h
or with .cpp
):
find -type f \( -name '*.h' -o -name '*.cpp' \) -exec grep "your pattern" {} +
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
And if you really want to use grep
, follow the syntax indicated to --include
:
grep "your pattern" -r --include=*.{cpp,h}
# ^^^^^^^^^^^^^^^^^^^
The easiest way is:
find . -type f -name '*.extension' 2>/dev/null | xargs grep -i string
Add 2>/dev/null
to kill the error output.
To include more file extensions and grep for password throughout the system:
find / -type f \( -name '*.conf' -o -name "*.log" -o -name "*.bak" \) 2>/dev/null |
xargs grep -i password
ag
(the silver searcher) has pretty simple syntax for this
-G --file-search-regex PATTERN
Only search files whose names match PATTERN.
so
ag -G *.h -G *.cpp CP_Image <path>
ag _string_to_find_ -G _filename_regex_
You should write "-exec grep " for each "-o -name ":
find . -name '*.h' -exec grep -Hn "CP_Image" {} \; -o -name '*.cpp' -exec grep -Hn "CP_Image" {} \;
Or group them by ( )
find . \( -name '*.h' -o -name '*.cpp' \) -exec grep -Hn "CP_Image" {} \;
Option '-Hn' shows the file name and line.
Here is a method I normally use to find .c and .h files:
tree -if | grep \\.[ch]\\b | xargs -n 1 grep -H "#include"
Or if you need the line number as well:
tree -if | grep \\.[ch]\\b | xargs -n 1 grep -nH "#include"
If you want to filter out extensions from the output of another command e.g. "git":
files=$(git diff --name-only --diff-filter=d origin/master... | grep -E '\.cpp$|\.h$')
for file in $files; do
echo "$file"
done
Success story sharing
grep -r -i --include \*.h --include \*.cpp CP_Image ~/path[12345]
grep -r -i --include="*.h" --include="*.cpp" CP_Image