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]
- 6,546
- 10
- 48
- 102
3 Answers
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))
- 20,999
- 2
- 37
- 69
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-x
find-diredRET (executefind-dired) - C-j (accept default directory :
.) -iname "*.foo"RET (enter command-line arguments)
Results are presented in a dired buffer.
- 19,520
- 4
- 51
- 74
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.
- 2,340
- 15
- 26