Emacs shell scripts – how to put initial options into the script?

Many unix variants only allow a single argument to the program on the shebang line. Sad, but true. If you use #!/usr/bin/env emacs so as not to depend on the location of the emacs executable, you can’t pass an argument at all.

Chaining scripts is a possibility on some systems, but that too is not supported everywhere.

You can go the time-honored route of writing a polyglot script: a script that is both a shell script and an Emacs Lisp script (like Perl’s if $running_under_some_shell, for example). It sure looks hackish, but it works.

Elisp comments begin with ;, which in the shell separates two commands. So we can use a ; followed by a shell instruction to switch over to Emacs, with the actual Lisp code beginning on the next line. Most shells don’t like an empty command though, so we need to find something that both the shell and Emacs treat as a no-op, to put before the ;. The shell no-op command is :; you can write it ":" as far as the shell is concerned, and Emacs parses that as a constant at top level which is also a no-op.

#! /bin/sh
":"; exec emacs --no-site-file --script "$0" -- "$@" # -*-emacs-lisp-*-
(print (+ 2 2))

Leave a Comment