2

Is there an equivalent of C's system(char*) or Python's os.system(string) for emacs --script?

I want to use Emacs for shell-scripting purposes. However, I cannot find a function that allows running an executable in a subprocess and connectings its STDOUT/STDERR directly to the terminal.

make-process, call-process, start-process, shell-command, async-shell-command all require a lot of additional code to forward the process output from either an intermediate Emacs buffer or by using filter functions.

I am looking for a solution that replicates the simplicity of int status = system("ls -l");. Ideally, it should be a builtin feature of Emacs to avoid having to set up EMACSLOADPATH.

2
  • I don't understand what you're asking for. Do you want to call Emacs, run some elisp in Emacs, and have the output sent to STDOUT? Or do you want to call Emacs, have it call another program in a subprocess, and then have the output from that program/subprocess sent to STDOUT?
    – Tyler
    Commented Nov 2, 2020 at 19:00
  • @Tyler The latter. For scripting use, calling a subprogram without losing its output, if any, is a pretty basic operation.
    – kdb
    Commented Nov 2, 2020 at 22:15

1 Answer 1

-1

The command shell-command-to-string will capture STOUT from a program to a string. You can then do what you like with that string in your script. Simply passing it to message will print it out to STDOUT:

emacs --batch --eval '(message (shell-command-to-string "ls -lh"))'

total 384K
drwxr-xr-x 2 smithty domain users 4.0K Oct 28 09:16 bin
drwxr-xr-x 9 smithty domain users 4.0K Nov 2 09:27 blogdown
drwxr-xr-x 2 smithty domain users 4.0K Oct 1 13:18 Desktop
drwxr-xr-x 2 smithty domain users 4.0K Nov 2 15:46 dl
drwxr-xr-x 2 smithty domain users 4.0K Oct 14 21:27 Documents
drwxr-xr-x 4 smithty domain users 4.0K Nov 1 17:14 hacking

3
  • 1
    Viable workaround for very short commands, but unlike system(...), but it fails on several levels to emulate system(...): It doesn't preserve the separation of STDERR and STDOUT, and it doesn't allow longer-running programs to provide feedback about their progress to the terminal, while they are still running. If the output is particularly large, and the emacs-lisp script is intended to be piped into another script, it may outright crash. Also, message prints to stdout, so it should be princ instead. Since it uses a buffer internally, it is also incredibly slow compared
    – kdb
    Commented Nov 4, 2020 at 8:04
  • to directly forwarding the output. Try time dd if=/dev/zero bs=1M count=32000 > /dev/null (1.4 seconds) vs emacs --batch --eval '(princ (shell-command-to-string "time dd if=/dev/zero bs=1M count=32000"))' > /dev/null. It should crash eventually for lack of memory on Windows, or worse, make the PC unresponsive on Linux due to heavy swapping, but it will take forever to happen.
    – kdb
    Commented Nov 4, 2020 at 8:04
  • I see. I've never gone that deep into shell scripting with Emacs. By the time I'm in a situation with requirements such as yours, I find it easier to stick with Bash, or other truly shell-oriented languages. You can do shell scripts in Emacs, but elisp is fundamentally designed for working with strings and buffers, rather than streams. Maybe someone else will know better, but I suspect you're getting into territory where it would be more efficient to work with a more conventional shell scripting language.
    – Tyler
    Commented Nov 4, 2020 at 14:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.