How to Write grep in Emacs Lisp

Buy Xah Emacs Tutorial. Master emacs benefits for life.
, , …,

This page shows you how to write a emacs lisp script to search files, similar to unix grep.


I want to write a elisp script that reports files in a dir that contain a string n times. The script is expected to search thru 5 thousand files.


Here's a very simple version. It reports number of matches.

;; -*- coding: utf-8 -*-
;; 2010-03-27
;; print file names of files that have n occurrences of a string, of a given dir

;; input dir
(setq inputDir "~/web/" ) ; In elisp, dir path should end with a slash

(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

        (insert-file-contents fPath nil nil nil t)

        (setq searchStr "somesearchstring" ) ; search string here

        (goto-char 1)
        (while (search-forward searchStr nil t)
          (setq ii (1+ ii)))

        ;; report if the occurrence is not n times
        (when (not (= ii 0))
            (princ (format "this many: %d %s\n" ii fPath)))))))

;; traverse the dir

(require 'find-lisp)

(let (outputBuffer)
  (setq outputBuffer "*my occur output*" )
  (with-output-to-temp-buffer outputBuffer
    (mapc 'my-process-file (find-lisp-find-files inputDir "\\.html$"))
    (princ "Done deal!")))

The code is pretty simple. At the bottom, the code visits every file in a dir. For each file, it calls (my-process-file fPath). The “my-process-file” function creates a temp buffer, inserts the file content in it, then do search inside the temp buffer. We do this because it's faster.

(with temp buffer, emacs doesn't do syntax-coloring (which is very slow), disables undo, or any other thing emacs normally do when opening a file for interactive edit.)

To run the file, you can call eval-buffer. 〔➤ Emacs: How to Evaluate Emacs Lisp Code〕 〔➤ Emacs Lisp: Run Current File

The elisp idioms used in this script are explained at: Text Processing with Emacs Lisp Batch Style.

On 5k files, the script takes 20 seconds on a average year 2011 computer. (when files are not cached.)

Why can't i just call the unix grep command?

See: Problems of Calling Unix grep in Emacs.

Emacs Package: xah-find.el

For the full featured version of this command, see the package Emacs: Find/Replace in Pure Elisp xah-find.el.


For applications of this script, with slight variations, see:

For simple example of writing grep/sed/awk in Python and Perl, see:

Like it? Buy Xah Emacs Tutorial.