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.
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.
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)
Commonly used functions to manipulate files ＆ dirs.
(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)))))
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 Dired: Opening Files in External Apps.
To get arguments passed from the command line, use the built-in variable argv.
For some practical examples of batch style text processing, see: