Elisp: Writing Elisp Script

By Xah Lee. Date: . Last updated: .

This page shows common programing solutions of emacs lisp for batch text processing. Typically the type of tasks one would do in unix shell tools or Python, Ruby . For example, find replace on a list of given files or dir, process (small sized) log files, compile a bunch of files, generating a report.

Run Emacs Lisp Script in Shell

Elisp: Run Elisp Script in Shell

Read / Write to File

Read-Only Text Processing

To process thousands of files, read only, use with-temp-buffer.

(defun my-process-file (fPath)
  "Process the file at path FPATH …"
    (insert-file-contents fPath)
    ;; process it …

Note: you should not use find-file or write-file, because they have many side-effects and is slow. See: Emacs Lisp Text Processing: find-file vs with-temp-buffer.

(info "(elisp) Current Buffer")

Modify Files

If you want to change every file you opened, use with-temp-file.

(defun my-process-file (fPath)
  "Process the file at path FPATH …"
  (with-temp-file fPath
    (insert-file-contents fPath)

    ;; process text code here


(info "(elisp) Writing to Files")

If you want to write to file ONLY when you actually changed the file, you can create flag variable and Alt+x write-region, like this:

(defun my-process-file (fPath)
  "Process the file at path FPATH …"
  (let ((fileChanged-p nil))
      (insert-file-contents fPath)

      ;; process text
      ;; set fileChanged-p to t or nil

      (when fileChanged-p (write-region 1 (point-max) fPath)))))

Read File Content as String or List of Lines

Elisp: Read File Content as String or List of Lines

File and Directory Manipulation

Filename Manipulation

Commonly used functions to manipulate file names.

(file-name-directory f)      ; get dir path
(file-name-nondirectory f)   ; get file name

(file-name-extension f)      ; get suffix
(file-name-sans-extension f) ; remove suffix

(file-relative-name f)      ; get relative path
(expand-file-name f)        ; get full path

default-directory       ; get the current dir (this is a variable)

(info "(elisp) File Names")

File and Directory Manipulation

Commonly used functions to manipulate files and directories.

(file-exists-p FILENAME)

(rename-file FILE NEWNAME &optional OK-IF-ALREADY-EXISTS)


(delete-file FILE)

(set-file-modes FILE MODE)
;; get list of file names
(directory-files DIR &optional FULL MATCH NOSORT)

;; create a dir. Non existent paren dirs will be created
(make-directory DIR &optional PARENTS)

;; copy/delete whole dir
(delete-directory DIRECTORY &optional RECURSIVE) ; RECURSIVE option new in emacs 23.2
(copy-directory DIR NEWNAME &optional KEEP-TIME PARENTS) ; new in emacs 23.2

(info "(elisp) Files")

Example: make backup file.

(defun make-backup ()
  "Make a backup copy of current buffer's file.
Create a backup of current buffer's file.
The new file name is the old file name with trailing “~”, in the same dir.
If such a file already exist, append more “~”.
If the current buffer is not associated with a file, its a error."

  (let ( (fName (buffer-file-name))
         backupName )

    (if (null fname)
        (message "current buffer is not a file.")
        (setq backupName (concat fName "~"))

        (while (file-exists-p backupName)
          (setq backupName (concat backupName "~")))

        (copy-file fName backupName t)
        (message (concat "Backup saved as: " (file-name-nondirectory backupName)))))))

Find the Current Elisp Script's File Name Programmatically

Elisp: Get Script Name at Run Time, Call by Relative Path

Call Shell Command

Call a shell command, wait for it to finish before continuing, use shell-command or shell-command-to-string.

; call a shell command
(shell-command "cp /somepath/myfile.txt  /somepath")

; call a shell command and get its output
(shell-command-to-string "ls")

Call a shell command, but don't wait for it to finish before continuing, use start-process or start-process-shell-command. Here's a example:

;; open files in Linux desktop
 (lambda (x)
   (let ((process-connection-type nil))
     (start-process "" nil "xdg-open" x)) )

For detail, see: Emacs: Open File in External App.

(info "(elisp) Asynchronous Processes")

Traverse Directory

Elisp: Traverse Directory

Get Command Line Arguments

To get arguments passed from the command line, use the built-in variable argv.

Elisp: Get Command Line Arguments

Process Lines

Elisp: Functions on Line

Print, Princ, Prin1, Format, Message

Elisp: print, princ, prin1, format, message

Practical Examples

For some practical examples of batch style text processing, see:

( Thanks to Rubén Berenguel for a correction.) ( thx to Phil Hudson for a tip.)

Patreon me $5 patreon

Or Buy Xah Emacs Tutorial

Or buy a nice keyboard: Best Keyboard for Emacs

If you have a question, put $5 at patreon and message me.