I used to use the function below to call ack as a fast, recursive grep, but for whatever reason it stopped working. More precisely it returns no result. It probably happened when I updated Emacs or macOS, hard to say.

The ack is working from terminal without any issues.

Does anyone have any idea how to fix it? I also considering alternatives, but hopefully not too slow for big folders.

(defun my/rgrep ()
  (if (executable-find "ack")
    (let* ((regexp (grep-read-regexp))
            (dir (read-directory-name "Base directory: " nil default-directory t))
            (command (concat "ack '" regexp "' " dir)))
      (unless (file-accessible-directory-p dir)
        (error (concat "directory: '" dir "' is not accessible.")))
        (compilation-start command 'grep-mode))

EDIT: Sadly even rgrep doesn't work when evaluated as (progn (grep-compute-defaults) (rgrep "foo" "*.txt" "/Volumes/RAM_Disk/test")) where that folder has only one txt file with text "foo" it returns no matches. The generated find command below:

find . -type d \( -path \*/SCCS -o -path \*/RCS -o -path \*/CVS -o -path \*/MCVS -o -path \*/.src -o -path \*/.svn -o -path \*/.git -o -path \*/.hg -o -path \*/.bzr -o -path \*/_MTN -o -path \*/_darcs -o -path \*/\{arch\} \) -prune -o \! -type d \( -name .\#\* -o -name \*.o -o -name \*\~ -o -name \*.bin -o -name \*.lbin -o -name \*.so -o -name \*.a -o -name \*.ln -o -name \*.blg -o -name \*.bbl -o -name \*.elc -o -name \*.lof -o -name \*.glo -o -name \*.idx -o -name \*.lot -o -name \*.fmt -o -name \*.tfm -o -name \*.class -o -name \*.fas -o -name \*.lib -o -name \*.mem -o -name \*.x86f -o -name \*.sparcf -o -name \*.dfsl -o -name \*.pfsl -o -name \*.d64fsl -o -name \*.p64fsl -o -name \*.lx64fsl -o -name \*.lx32fsl -o -name \*.dx64fsl -o -name \*.dx32fsl -o -name \*.fx64fsl -o -name \*.fx32fsl -o -name \*.sx64fsl -o -name \*.sx32fsl -o -name \*.wx64fsl -o -name \*.wx32fsl -o -name \*.fasl -o -name \*.ufsl -o -name \*.fsl -o -name \*.dxl -o -name \*.lo -o -name \*.la -o -name \*.gmo -o -name \*.mo -o -name \*.toc -o -name \*.aux -o -name \*.cp -o -name \*.fn -o -name \*.ky -o -name \*.pg -o -name \*.tp -o -name \*.vr -o -name \*.cps -o -name \*.fns -o -name \*.kys -o -name \*.pgs -o -name \*.tps -o -name \*.vrs -o -name \*.pyc -o -name \*.pyo \) -prune -o  -type f \( -iregex \*.txt \) -exec grep -i -nH --null -e foo \{\} +

After more pondering on this, I found that there is also a problem with running rgrep or any alternative in tramp.

I think of making a universal my/rgrep function that will use default strategy like ack, and fallback to another strategy like ag and find/grep if the previous one wasn't found. Also making it work with tramp.

Because I already have defined config for ack that works well from the terminal I would put ack on the front of that list, but it shouldn't matter which one we put first.

Does anyone of you have this problem solved already, or at least have configured tramp to work well with rgrep?

  • Use (elisp)Edebug to learn what's happening. Note that (concat "ack '" regexp "' " dir) is buggy. Compilation commands are run via a shell, so use C-h f shell-quote-argument. Currently you're assuming that single-quoting will be fine, so I imagine your command will just break if REGEXP contained a single quote, and DIR isn't escaped at all.
    – phils
    Oct 15, 2020 at 19:26
  • Did you try rgrep ? (progn (grep-compute-defaults) (rgrep "<regex>" "<file-glob>" "<directory>")). Remember to add the (grep-compute-defaults) if you call rgrep programmatically. Oct 15, 2020 at 19:36
  • @phils thanks for mention that. This command used to work, but from time to time it might fail, but rarly so I kept using it. The problem is when I run this function it opens grep buffer with the command that it soupuse to run, but without any results, but when I copy it to the terminal it works and results are found.
    – Navidot
    Oct 15, 2020 at 21:25
  • @FirminMartin yes, I tried with plain rgrep, but I get no results as well. The generated command is ridiculously long so I can't even paste it here. Hard to say if generated command is correct because it's crazy long, complex and run forever when pasted to the terminal. This is why I wanted to adapt ack or similar in place of rgrep.
    – Navidot
    Oct 15, 2020 at 21:29
  • 1
    For some reason, your generated find command uses -iregex \*.txt which is wrong (even in my side), mine use -name \*.txt and it works. Maybe you can fix the issue by passing a regex at the second argument (e.g. .*.txt), but it's not the expected behaviour of rgrep. I'll take a look on the source code. Oct 16, 2020 at 8:10

1 Answer 1


Thanks for suggestions in comments, especially by Firmin Martin, I managed to find an answer to the problem. It turned out that the variable find-name-arg was set to -iregex which caused the issue in rgrep, no matter if used with ack or with regular grep. After brinding is back to default -iname the rgrep works fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.