Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to process a series of files with elisp?

Tags:

text

emacs

elisp

I'm a newbie to programming, so please bear with me here...

I have a directory full of files called "foo01.txt", "foo02.txt", etc. and a function called MyFunction. I want to open each file as a buffer, run MyFunction on it, write the buffer to its file, kill the buffer and move on to the next file in the series until all the files are done.

I think all the pieces I need to do this are described in the Cookbook (http://emacswiki.org/emacs/ElispCookbook) but I'm not really understanding how to put it all together. Thanks!

like image 955
Brian Z Avatar asked Dec 26 '22 10:12

Brian Z


2 Answers

Answer

If you're looking for an answer in pure elisp, you could do something like this:

(defun process-file (f)
  (save-excursion 
    (find-file f)
    (my-function)     ; Call your function here.
    (write-file f)
    (kill-buffer (current-buffer))))

(defun process-files (dir) 
  (mapc 'process-file
        (directory-files dir t ".txt$")))

process-files will iterate over each file in a given directory and apply process-file to all .txt files. You can call it like so:

(process-files "~/target-directory")

You can copy this into a *scratch* buffer and play around with the individual parts. The most interesting functions are:

  • mapc - applies a function to each item in a list
  • directory-files - gets all files and folders in a directory, in this case retrieving all .txt files
  • find-file - opens a file in a buffer (this is what is run when you type C-x C-f)

Learning Lisp

If you're learning Lisp for its own sake, I can recommend Practical Common Lisp. You'll be able to work through a surprising amount of the book using Elisp. Otherwise, download a Common Lisp environment like SBCL.

like image 200
Chris Barrett Avatar answered Jan 02 '23 11:01

Chris Barrett


The good in Emacs is that there are often many ways to solve a given problem, thanks to Emacs openness.

For instance, you could learn an easy trick in Emacs, that will help you now and in the future:

Here is a dired listing, eg from C-x f/home/me/mydir/

  /home/me/mydir:
  total used in directory 32 available 5575136
  drwxr-xr-x  10 me  brainers   340 Jan 18 15:50 .
  drwxr-xr-x  78 me  brainers  2652 Feb  2 18:08 ..
  -rw-r--r--   4 me  brainers   136 Apr  1  2012 a.txt
  -rw-r--r--  16 me  brainers   544 Feb  1 09:56 b.txt
  -rw-r--r--   6 me  brainers   204 Apr  6  2012 c.txt

go to the first one (using up and down keys), ie a.txt, and do

  • C-x ( to start a macro recording
  • f to open that file
  • M-x myfunction to run that myfunction function
  • C-x C-s to save the file
  • C-x k to close that file, back to dired
  • down key to go to next file (b.txt in this case)
  • C-x ) to end the macro

then for each file (from b.txt), do

  • C-x e to execute the macro, it will do the same with b.txt, and then point to c.txt. (You could just do e to re-execute the macro if you don't do anything in between two macro executions)

Be careful not to run the macro on something that you don't want to be processed.

Notes:

  • if you make any mistake during the creation of the macro, Emacs will interrupt the recording process (thus, C-x ) will complain there is no macro being recorded). In this case the macro has to be started again from C-x (.
  • C-key is Control key, M-key is Meta key usually Alt-key. And C-x k means Control x then k key.
like image 26
Déjà vu Avatar answered Jan 02 '23 10:01

Déjà vu