[For the Emacs mode for editing DOS batch files, see DosScripts.]
According to the EmacsManual:
‘-batch’ causes Emacs to run noninteractively. In this mode, Emacs does not read commands from the terminal, it does not alter the terminal modes, and it does not expect to be outputting to an erasable screen. The idea is that you specify Lisp programs to run; when they are finished, Emacs should exit. […]The EmacsManual does not give any examples so here are a few.
You can call simulate an EmacsLisp-based script by putting this in a batch script:
emacs -batch -l ~/.emacs.editor --eval="(require 'foo)" \ --eval="(require 'bar)" \ --eval="(some-function $*)"
Starting with the Emacs 22, you can write Emacs scripts just as if you were writing Bash or Perl scripts, when you include this at the top of your script file:
#!/usr/bin/emacs --script
One use of batch scripting is to run a predicate over a collection of files. For example, to use ‘check-parens’ and exit with an error code 1 if ‘check-parens’ throws an exception:
emacs file --batch --eval="(condition-case nil (check-parens) (error (kill-emacs 1)))"
Easily turned into a shell script to print out the names of files with detected imbalances:
for file in *.txt; do emacs "$file" --batch --eval="(condition-case nil (check-parens) (error (kill-emacs 1)))" &> /dev/null || echo $file; done
emacs -batch sample.c --eval '(indent-region (point-min) (point-max) nil)' -f save-buffer
The above opens the file sample.c and runs ‘indent-region’ from the beginning (‘point-min’) to the end (‘point-max’) of the file, then saves the file. Because Emacs is thoughtful, it automatically saves a copy of the original file to sample.c~.
Emacs is provided with an intelligent paragraph filling command, which can be helpful for use on numerous files. To have Emacs fix the long lines of one or more files from the command-line, use the following command:
emacs -batch long-file.txt --eval '(fill-region (point-min) (point-max))' -f save-buffer
Emacs will use the filling rules for the mode the file is opened in, and fill all lines in the file. This could have unexpected results in certain modes.
Here is a link to a script that wraps up the command so it can be conveniently used on the command line with command line arguments:
Emacs can, from the command-line, update or insert Texinfo menus and nodes in a Texinfo document using the ‘texinfo-every-node-update’ and ‘texinfo-all-menus-update’ commands. This is especially helpful when a Texinfo file is being generated or converted from another source document. Consider the following MakeFILE rule which can convert some OTHER format into Texinfo (where OTHER is some other document format like XML or HTML):
%.texi: %.other $(OTHER2TEXI)
$(OTHER2TEXI) $< > $@
emacs -batch $@ \
-f texinfo-every-node-update -f texinfo-all-menus-update \
-f save-bufferThe example script shs-example demonstrates all the things you’d want to do with emacs scripts, and is meant to serve as a tutorial (I am teaching myself and improvements are very welcome) as well as demonstrate some useful functions from shs.el. Save these files somewhere in your bash path, change the path to that path in example-emacs-script and change the “#/usr/local/bin/emacs” address call to that of your actual Emacs path. Then, on bash prompt, type example-emacs-script.
(Note: Unfortunately these links are all dead. Wouldn’t be possible to put the code on EmacsWiki itself?)
(See: https://lists.gnu.org/archive/html/gnu-emacs-sources/2005-01/msg00013.html)
If active Emacs developers are reading this, we’d like to point out that (princ) in batch-mode prints to stdout, as opposed to stderr, which is not what the EmacsLispReference says. On the other hand, that is the only way at this time (we think) that you can print to stdout through an emacs batch script, so we hope that this “bug” is not fixed, but retained as a feature.
This is not a bug. princ function and all the print functions) direct their output depending on the variable standard-output. This variable can be set to a buffer, a marker, any function of 1 argument or the symbol t. The last case is the default. In interactive mode the output goes to the echo area. In batch mode it is directed to the normal stdout. The message function prints to stderr in batch mode. Perhaps there is an error in the documentation you referenced above (I have not checked)
It seems to have been corrected:
Example:
@"c:\Program Files\Emacs\emacs-21.3\bin\emacs.exe" -batch -no-site-file -q ^ -eval "(unless (y-or-n-p \"Do you want to continue? \") (kill-emacs 1)) @if %errorlevel% GTR 0 goto fin
Emacs batch mode does not read your personal config (or any config, it’s equivalent to -Q) so you don’t get packages loaded.
You can do whatever you were going to do though, just {{{package-initialize}}} when you eval. Here’s how I build packages using ElpaKit, which is itself a package:
emacs -batch --eval '(progn(package-initialize)(elpakit-make-multi "~/work/elmarmalade"))'
Nothing else special is required, except the package directory (which is {{{~/.emacs.d/elpa}}}) to be in the normal place.
It does seem that this would be a useful additional startup option, batch but with your packages and not your config.
If an interactive function takes an argument, Emacs will print the minibuffer prompt and wait for input at the command line. But if you give it something on STDIN, Emacs will use that instead. So you can have a script like
#!/bin/sh
echo "$@" | emacs --batch -l ~/.emacs.d/lisp/mything.el -f mything
that can be called like `mything.sh “here’s some input”` to have “here’s some input” passed to the mything function defined in mything.el. I used to maintain two versions of some things for use from emacs and from command line but now porting everything to elisp and making stub scripts like this.
We need a term more descriptive than “scripting” for this, since some people think that writing an emacs package is scripting. “batch mode” kind of implies no interactivity, which isn’t true. “command line or executable scripting with emacs lisp” is a mouthful. Maybe “scripting” is the best.
Scripting is within a hair of opening up a huge new market for emacs. People who use bash or Python or whatever could be using emacs:
The EASILY FIXABLE THINGS holding it back are:
Does anybody agree? Drop me a line just to let me know somebody read this.
(gambarimasu who is at gmail.com)
See also EmacsScripts.