[For the Emacs mode for editing DOS batch files, see DosScripts.]

According to the EmacsManual:

The command-line option ‘-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. […]
Any Lisp program output that would normally go to the echo area, either using message, or using prin1, etc., with t as the stream, goes instead to Emacs’s standard descriptors when in batch mode: message writes to the standard error descriptor, while prin1 and other print functions write to the standard output. Similarly, input that would normally come from the minibuffer is read from the standard input descriptor. Thus, Emacs behaves much like a noninteractive application program. […]

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

Error codes

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

Indenting C files

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

Filling Paragraphs

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:

Texinfo Files

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-buffer

Shell Script

The 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?)


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:

Any Lisp program output that would normally go to the echo area, either using message, or using prin1, etc., with t as the stream, goes instead to Emacs’s standard descriptors when in batch mode: message writes to the standard error descriptor, while prin1 and other print functions write to the standard output.

Prompts in w32 cmd-files


@"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

Using packages in your script

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.

Passing args to emacs lisp functions from the command line

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

echo "$@" | emacs --batch -l ~/.emacs.d/lisp/mything.el -f mything

that can be called like ` “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:

  • you’re already using it
  • it’s lisp
  • it’s pretty cl compatible
  • it’s already installed
  • it’s portable
  • it does everything
  • it won’t go away
  • it supports unique features like buffers
  • you can record a keyboard macro and save the script

The EASILY FIXABLE THINGS holding it back are:

  • fear that emacs lisp isn’t a real language (as if bash were)
    • some people don’t know about (require ‘cl) or lexical-let
  • uncertainty about whether it will handle stdio and the like
    • how to get rid of “Loading” messages?
    • how to pipe something to a command and back to emacs lisp?
    • is “a few minor exceptions” above famous last words?
  • doubt that this usage will be supported
    • see note about princ above
    • no detailed discussion in documentation
    • paucity of open source shebang scripts

Does anybody agree? Drop me a line just to let me know somebody read this.

(gambarimasu who is at

See also

See also EmacsScripts.