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!
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.
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.