Elisp: Call Shell Command

By Xah Lee. Date: . Last updated: .

Call Shell Command, Wait, Get Result

shell-command
Call a shell command, wait for it to finish.
; call a shell command
(shell-command "ls")
shell-command-to-string
Call a shell command, wait for it to finish, get its output.
; call a shell command and get its output
(shell-command-to-string "ls")

Start External Process

It is more efficient is to launch external app directly than launching a shell to call external command.

Also, you do not have to deal with complicated character escapes in arg or file name involving apostrophe, quote, backslash.

call-process
(call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS)

Call PROGRAM in separate process, wait for it to finish. (unless DESTINATION is 0). PROGRAM is searched in exec-path

  • INFILE (nil means `null-device') is the input file (a relative path). see also call-process-region
  • DESTINATION is a buffer for output (including standard error.).
    • Or t for current buffer.
    • Or nil for discard output.
    • Or 0 for don't wait for the program to terminate..
    • Or (:file FILE) means write to file. (overwrite existing)
    • Or (REAL-BUFFER STDERR-FILE). (See elisp manual.)
  • DISPLAY non-nil means redisplay buffer as output is inserted.
  • ARGS are strings passed as command arguments to PROGRAM. (each is a string). If you have a list, use apply. [see Elisp: Apply Function (List to Args)]
;; example of call-process on linux
;; passing it a file path
(cond
 ((eq system-type 'windows-nt)
  nil)
 ((eq system-type 'darwin)
  nil)
 ((eq system-type 'gnu/linux)
  (call-process
   shell-file-name nil 0 nil
   shell-command-switch
   (format "%s %s"
           "xdg-open"
           (file-name-directory xpath)))))
;; example of call-process
;; and start-process
;; , when you need to feed it a lot file names

(let ((xoutBuf (get-buffer-create "*xah remove metadata output*"))
      (xshortNames (mapcar 'file-relative-name FileList)))
  (if Wait-p
      (apply
       'call-process
       (append
        (list "exiftool" nil xoutBuf t "-all=" "-overwrite_original")
        xshortNames nil))
    (let ((process-connection-type nil))
      (apply
       'start-process
       (append
        (list "exiftool" xoutBuf "exiftool" "-all=" "-overwrite_original")
        xshortNames nil))))
  (princ "Called xah-dired-remove-all-metadata"))
start-process
(start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)

Start a program in a subprocess. (do not wait for it to finish) Return the process object for it.

  • NAME is name for process. Can be any.
  • BUFFER is the buffer (or buffer name) for process output (both standard output and standard error streams). Or nil.
  • PROGRAM is the program file name to start. It is searched for in exec-path. If nil, just associate a pty with the buffer.
  • PROGRAM-ARGS are arguments (each is a string). If you have a list, use apply. [see Elisp: Apply Function (List to Args)]
;; example of start-process and call-process

;; open a list of files in operating system's default app
(cond
 ((eq system-type 'windows-nt)
  (let ((xoutBuf (get-buffer-create "*xah open in external app*"))
        (xcmdlist (list "PowerShell" "-Command" "Invoke-Item" "-LiteralPath")))
    (mapc
     (lambda (x)
       (message "%s" x)
       (apply
        'start-process
        (append
         (list "xah open in external app" xoutBuf) xcmdlist
         (list (format "'%s'" (if (string-match "'" x) (replace-match "`'" t t x) x))) nil)))
     xfileList)))
 ((eq system-type 'darwin)
  (mapc (lambda (xfpath) (shell-command (concat "open " (shell-quote-argument xfpath)))) xfileList))
 ((eq system-type 'gnu/linux)
  (mapc
   (lambda (xfpath)
     (call-process
      shell-file-name nil 0 nil
      shell-command-switch
      (format "%s %s"
              "xdg-open"
              (shell-quote-argument xfpath))))
   xfileList))
 ((eq system-type 'berkeley-unix)
  (mapc
   (lambda (xfpath)
     (let ((process-connection-type nil))
       (start-process "" nil "xdg-open" xfpath)))
   xfileList)))
start-process-shell-command
(start-process-shell-command NAME BUFFER COMMAND)

same as start-process, but use a single string for the external command and args.

make-process
(make-process &rest ARGS)

The core function for creating process. similar to start-process. See elisp manual.

Reference

Elisp, scripts