Elisp: Write grep
This page shows you how to write a emacs lisp script to search files, similar to unix grep.
Here's a very simple version. It reports number of matches.
;; -*- coding: utf-8 -*- ;; print file names of files that have n occurrences of a string, of a given dir ;; version 2019-01-13 ;; input dir ;; In elisp, dir path should end with a slash (setq inputDir "/Users/xah/web/ergoemacs_org/" ) (setq findStr "stuff") (defun my-process-file (fPath) "Process the file at FPATH " (let (myBuffer p1 p2 (ii 0) searchStr) (when (and (not (string-match "/xx" fPath))) ; exclude some dir (with-temp-buffer (insert-file-contents fPath nil nil nil t) (setq searchStr findStr ) (goto-char (point-min)) (while (search-forward searchStr nil t) (setq ii (1+ ii))) ;; report if the occurrence is not n times (when (not (= ii 0)) (princ (format "%d %s\n" ii fPath))))))) ;; walk the dir (let (outputBuffer) (setq outputBuffer "*my find output*" ) (with-output-to-temp-buffer outputBuffer (mapc 'my-process-file (directory-files-recursively inputDir "\.html$" )) (princ "Done")))
At the bottom, the code visits every file in
a dir. For each file, it calls
my-process-file
. That function creates a temp buffer, inserts the file content
in it, then do search inside the temp buffer. We use a temp buffer because it's faster.
〔see Emacs Lisp Text Processing: find-file vs with-temp-buffer〕
To run the file, just Alt+x eval-buffer
.
〔see Evaluate Emacs Lisp Code〕
On 9838 html files, the script takes 40 seconds on a “Late 2014” Mac Mini computer, when files are not cached, on a spinning harddisk.
When running a second time, it just take 6 seconds.
What is wrong with unix grep command?
See: Problems of grep in Emacs.
Emacs Package: xah-find.el
For the full featured version of this command, see the package Emacs: Xah Find Replace (xah-find.el) 📦.