Emacs Lisp Idioms for Text Processing in Batch Style
This page shows common programing patterns of emacs lisp for batch text processing. Typically the type of tasks one would do in unix shell tools or Perl. 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.
If you don't know elisp, see: Emacs Lisp Basics.
Run Emacs Lisp Script in Shell
Read / Write to File
Read-Only Text Processing
To process thousands of files, read only, use
(defun my-process-file (fPath) "Process the file at path FPATH …" (with-temp-buffer (insert-file-contents fPath) ;; process it … ))
If you want to write to file ONLY when you actually changed the file, you can create flag variable and call
write-region, like this:
(defun my-process-file (fPath) "Process the file at path FPATH …" (let ((fileChanged-p nil)) (with-temp-buffer (insert-file-contents fPath) ;; process text ;; set fileChanged-p to t or nil (when fileChanged-p (write-region 1 (point-max) fPath)))))
If you always need to change every file, use
Note: you should not use
write-file, because they have many side-effects and is slow.
See: Emacs Lisp Text Processing: find-file vs with-temp-buffer.
Read File Content as String or List of Lines
File and Directory 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)
File and Directory Manipulation
Commonly used functions to manipulate files and directorys.
(file-exists-p FILENAME) (rename-file FILE NEWNAME &optional OK-IF-ALREADY-EXISTS) (copy-file FILE NEWNAME &optional OK-IF-ALREADY-EXISTS KEEP-TIME PRESERVE-UID-GID) (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
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." (interactive) (let (fName backupName) (setq fName (buffer-file-name)) (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
Call Shell Command
Call a shell command, wait for it to finish before continuing, use
; idiom for calling a shell command (shell-command "cp /somepath/myfile.txt /somepath") ; idiom for calling 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-shell-command. Here a example:
;; open files in Linux desktop (mapc (lambda (fPath) (let ((process-connection-type nil)) (start-process "" nil "xdg-open" fPath)) ) myFileList)
For detail, see: Emacs: Open File in External App.
Get Command Line Arguments
To get arguments passed from the command line, use the built-in variable argv.
Print, Princ, Prin1, Format, Message
For some practical examples of batch style text processing, see:
- How to Write grep in Emacs Lisp
- Emacs Lisp: Generate Web Links Report
- Emacs Lisp: Create Sitemap
- Emacs Lisp: Batch Transform HTML to HTML5 “figure” Tag
- Emacs Lisp: Batch Script to Validate Matching Brackets
or, buy something from Best Keyboard for Emacs