ELisp: Write grep

By Xah Lee. Date: . Last updated: .

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).

Find Replace Scripts