I'm using Emacs for quite some time and I still somehow fail to understand what is the best way to (recursively) grep for a string within a (project) directory and get the results presented either as a dired buffer or in some even more useful way. Please enlighten me.
-
Have you tried out using `helm-projectile-grep` command (if you have helm projectile installed) or `projectile-grep` ? – Chakravarthy Raghunandan Aug 17 '16 at 11:16
-
I do not know what `helm` or `projectile` is, but if it is a recommended tool, I would install and learn it. – Boris Stitnicky Aug 17 '16 at 11:27
-
Yes, projectile is a package that provides an easy way to do what you mentioned in the question with the command `projectile-grep`. Also, I HIGHLY recommend you install `helm` package. I can't imagine running emacs without `helm` and `helm-projectile`. You might also be interesting in `helm-ag` package (which provides a helm interface for silver searcher in emacs, which is supposedly faster than grep or ack). – Chakravarthy Raghunandan Aug 17 '16 at 11:31
-
Now make those comments into a full-fledged answer lol. – Boris Stitnicky Aug 17 '16 at 12:12
-
Possible duplicate of [Is there a way to use query-replace from grep/ack/ag output modes?](http://emacs.stackexchange.com/questions/212/is-there-a-way-to-use-query-replace-from-grep-ack-ag-output-modes) – Kaushal Modi Aug 17 '16 at 12:13
-
Possible duplicate of [Recursive grep in directory with helm and/or projectile?](http://emacs.stackexchange.com/questions/10842/recursive-grep-in-directory-with-helm-and-or-projectile) – Chakravarthy Raghunandan Aug 17 '16 at 12:14
-
My link points to a question about query replace, but I believe it strongly applies to your question too. My answer to that question uses ag instead of grep to search through the whole project. (I then choose to use wgrep+multiple cursors to replace all the matches.) – Kaushal Modi Aug 17 '16 at 12:15
-
3So that the question is more useful and easier to find for future Google and forum searchers, perhaps consider modifying the *title* of the question to include the word **recursively**, and consider limiting the scope -- e.g., **How to recursively grep file contents in a directory / subdirectories**. That's just an example -- it could be something else instead. – lawlist Aug 17 '16 at 17:19
-
2While the comments and answers so far have suggested a number of packages to do this in various fancy ways, I don't see from your question why simple `M-x grep` doesn't do what you need. It let's you give an arbitrary command line, I sometimes use `find` there when I need the recursion. – MAP Aug 19 '16 at 07:36
-
Thanks for the suggestion about the title. It will take me some time to absorb the knowledge I received here from all of you and find out what works the best for me. Maybe I'm lame or something, but grepping was a long-standing problem for me and I hope my question can help others, too. – Boris Stitnicky Aug 19 '16 at 08:59
5 Answers
Well, since the original question doesn't mention rgrep
, I'll go ahead and point it out here. This is the simplest option already built into Emacs, and I've found it to be more than sufficient for most things.
From the documentation,
Recursively grep for REGEXP in FILES in directory tree rooted at DIR.
The search is limited to file names matching shell pattern FILES.
So, for instance, to search all python files beneath my home directory for uses ofsome_function
, I would call it with some_function
, *.py
, ~/
as the arguments. Results are displayed in a new buffer.

- 2,181
- 16
- 32
-
1Might want to mentioned `find-grep-dired` as well since OP mentioned "results presented either as a dired buffer or..." – npostavs Aug 18 '16 at 10:52
-
@npostavs I haven't used `find-grep-dired` myself, feel free to add it to the answer. – user2699 Aug 18 '16 at 15:12
-
1I once experimented with the likes of ack and ag, on the assumption that I should be switching from rgrep to something using those, because they were supposed to be better. In the end I stayed with rgrep, because I found no benefit to changing! On the command line there's certainly a case to be made, but in Emacs `rgrep` does such a good job of targeting the search that there were no significant speed differences between them. (I want to say that rgrep was fractionally *faster* in some cases, but I don't remember for sure.) – phils Aug 31 '16 at 05:39
-
1Note that `next-error` and `previous-error` can be used to navigate through the result set. I find `M-g M-n` and `M-g M-p` the most convenient of the standard bindings. – phils Aug 31 '16 at 05:50
-
`find-grep-dired` doesn't give me a buffer with cross-referencing links. `rgrep` does it for me and that last suggestion about `next-error` `previous-error` is fantastic! My only quibble is that all the messy command execution output at the start of the buffer. – robert Feb 22 '18 at 11:23
-
correction. `find-grep-dired` does work like this, there was a subtle error in my configuration (`find-ls-option` was being confused by tabs in my `find` implementation's `-ls` output). The output is still quite verbose though so I think I still prefer the `rgrep` approach. – robert Feb 22 '18 at 15:02
-
I happily use M-x find-grep-dired
for years. It returns the results as a dired buffer, which you could use.

- 6,647
- 14
- 20
-
I've had some difficulty with getting the cross-reference linking to work with this. It's configuration is quite nasty (`find-ls-option`) and after all that you end up with something that's quite verbose because it doesn't work without having the date before the filename! – robert Feb 22 '18 at 15:05
-
Solution 1 (best solution):
Install counsel (https://github.com/abo-abo/swiper/blob/master/counsel.el)
Then M-x counsel-git-grep
.
No setup needed (git knows the project root and files to exclude). Both git grep
and counsel
is efficient.
The project need be managed by git.
counsel requires ivy-mode.
Solution 2:
This solution uses grep and works on any project. It's inferior to the Solution 1 because it's slower and need manual setup. It's also based on ivy-mode.
(defvar simple-project-root "~/.emacs.d")
(defun simple-grep ()
(interactive)
(unless (featurep 'ivy)
(require 'ivy))
(let* ((default-directory (file-name-as-directory simple-project-root))
(keyword (read-string "Keyword:")))
(ivy-read (format "Grep at %s:" simple-project-root)
(split-string (shell-command-to-string (format "grep -rsnI %s ." keyword)) "\n" t)
:action (lambda (val)
(let* ((lst (split-string val ":"))
(linenum (string-to-number (cadr lst))))
;; open file
(find-file (car lst))
;; goto line if line number exists
(when (and linenum (> linenum 0))
(goto-char (point-min))
(forward-line (1- linenum))))))))
You need create .dir-locals.el to setup simple-project-root
, see https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html for technical details
The code in solution 2 is just a prototype. My real implementation is much more complex. See counsel-etags-grep
in https://github.com/redguardtoo/counsel-etags/blob/master/counsel-etags.el
Summary:
Those are the best two solutions I know.
If any other better solutions exist, they need at least solve below problems to be production-ready,
how to get the keyword to grep (for example, get keyword from selected region)
escape the keyword
if more efficient grep program exist, we should use it (ripgrep, the_silver_searcher/ag, ... etc), or else fallback the default grep
candidate window should use full width of screen and users can filter candidates interactively (that's why people use ivy or helm)
we should show the relative path in candidate window
able to re-use previous grepped result. So previous result should be saved. You can use
ivy-resume
fromivy
orhelm-resume
fromhelm
When you save previous grepped result, the context of previous result should also be saved. For example, in the code of of Solution 2.
default-directory
is context. See https://github.com/abo-abo/swiper/issues/591 for more details.Extended regular expression should be used because it's simpler and is already used by
counsel-git-grep
and the the_silver_searcher/ag.

- 4,781
- 18
- 36
Here is an example of a custom grep function that recursively greps file contents (using a regexp for the search term) in a directory and its subdirectories, and displays the results with lines of context before and after. The built-in compile.el
and grep.el
libraries provide for several methods to jump to the location in the file containing the search results. There is no need to install anything else for this example to work -- all that is needed is a full version of Emacs and a computer that has the grep
utility installed. The variable grep-program
can be adjusted to point to a particular location of the grep
utility if the default is not sufficient.
(defun recursive-grep ()
"Recursively grep file contents. `i` case insensitive; `n` print line number;
`I` ignore binary files; `E` extended regular expressions; `r` recursive"
(interactive)
(let* ((search-term (read-string "regex: "))
(search-path
(directory-file-name (expand-file-name (read-directory-name "directory: "))))
(default-directory (file-name-as-directory search-path))
(grep-command
(concat
grep-program
" "
"-inIEr --color=always -C2"
" "
search-term
" "
search-path)))
(compilation-start grep-command 'grep-mode (lambda (mode) "*grep*") nil)))

- 18,826
- 5
- 37
- 118
-
While the question does not seek how to simultaneously modify multiple files that are returned as results by the above grep function, I find it very helpful to use `multiple-cursors` and `wgrep`. It makes modifying multiple files in one fell swoop a breeze. Said libraries, however, would need to be installed if those features are desired. – lawlist Aug 17 '16 at 17:11
-
-
1@npostavs -- I found the built-in `rgrep` to be time-consuming to customize to my preferred regex search criteria, and I chose to hard-code everything in a custom function (which I use several times each day). If you would like to write-up an alternative answer that describes how to customize `rgrep`, that would be helpful to other forum readers in the future. – lawlist Aug 17 '16 at 17:41
I'd like to add another solution to @chen bin's solution which also uses counsel
(but you don't need to have a project maintained by git
for this).
You need to install ag (the silver searcher) and counsel
provides the command counsel-ag
which searches the current directory for the entered string.
If you want to search within a project(not just the current working directory), add this to your .emacs
:-
(defun rag/counsel-ag-project-at-point ()
"use counsel ag to search for the word at point in the project"
(interactive)
(counsel-ag (thing-at-point 'symbol) (projectile-project-root)))
This function will use ag
to recursively search the project root directory.
Edit: the above function defaults to the symbol at point for searching. If you do not like that behaviour, replace (thing-at-point 'symbol)
with nil
. And if you want the search results in it's own buffer press C-c C-o
Edit2: if you've ripgrep
installed, you can replace counsel-ag
with counsel-rg
in the above function and it'll just as fine :)

- 3,132
- 2
- 18
- 42
-
Is `projectile-project-root` useable to find Rails project root? – Boris Stitnicky Dec 07 '16 at 13:49
-
Yes, as long as it's a valid projectile project it will work. There was some package called projectile-rails I think. – Chakravarthy Raghunandan Dec 07 '16 at 14:24
-
-
It's a common style that people often use when writing their own functions(you can see it being done by a lot others if you browse their emacs config). All the functions I defined begin with `rag/` prefix and that makes them easy to find under `M-x` :) – Chakravarthy Raghunandan Dec 07 '16 at 16:33
-