0

I am looking for a command M-x find in Emacs, which behave exactly like M-x grep (allows to modify the command, prints the output nicely including links to the found files, ...) and which executes find . -iname '*|*' (with the cursor placed at the vertical bar -- for inserting a search pattern -- if not too complicated to implement). Has anyone implemented this before? [I am aware of M-x find-grep]

Marius Hofert
  • 6,546
  • 10
  • 48
  • 102

3 Answers3

3

Let's start with M-xfind-dired that does almost what you want: it reads directory from minibuffer, defaulting to current directory, and then reads other find arguments. The result is opened in dired mode, and I think it's as nicely as it can get (if you think that dired is too verbose, check out dired-details and maybe dired-details+ packages at MELPA).

Now let's make it start with -iname ** with a cursor between the stars when it's asking for options. Looking at find-dired source, we can see that it uses the value of find-args as an initial input argument to read-string. This argument is obsolete and deprecated but awfully useful. One of its features (as we read in read-from-minibuffer description) is providing a default point position when a cons of a string and an integer is given.

(defun marius/find-dired ()
  (interactive)
  (let ((find-args '("-iname '**'" . 10)))
    (call-interactively 'find-dired)))

We added single quotes around stars in '**' because the arguments are subject to shell expansion.

Instead of reading our own arguments from the minibuffer, we just rebind find-args and delegate all the rest to find-dired. Normally find-dired remembers last arguments you enter in find-args so they become the new default. Rebinding it with let ensures that this modification from our call to find-dired will be thrown away, so regular find-dired will use the arguments given to the latest regular find-dired. It probably doesn't matter if you don't use regular find-dired. If you want find arguments given to our wrapper to be used by regular find-dired, use the following definition instead:

(defun marius/find-dired ()
  (interactive)
  (setq find-args '("-iname '**'" . 10))
  (call-interactively 'find-dired))
Anton Kovalenko
  • 20,999
  • 2
  • 37
  • 69
1

I think that find-dired fulfills your requirements (except it doesn't initialize the command with "-iname" and lets you enter it).

For example:

  • M-xfind-diredRET (execute find-dired)
  • C-j (accept default directory : .)
  • -iname "*.foo" RET (enter command-line arguments)

Results are presented in a dired buffer.

François Févotte
  • 19,520
  • 4
  • 51
  • 74
0

You can start with:

(defun eab/find-grep ()
  (interactive)
  (let ((grep-host-defaults-alist nil)
        (grep-find-command
         `(,"find . -iname '**' -type f -print0 | xargs -0 -e grep -nH -m 1 -e \"^\"" . 17)))
    (call-interactively 'find-grep)))

Also I use:

(defun eab/grep ()
  (interactive)
  (let ((grep-host-defaults-alist nil)
        (grep-command
         `(,(concat "grep -i -nH -e  *."
                    (ignore-errors
                      (file-name-extension buffer-file-name))) . 16)))
    (call-interactively 'grep)))

EDIT: Now grep-find-command is for searching only first line of each file by default.

artscan
  • 2,340
  • 15
  • 26