Function: shell-command

shell-command is an interactive and byte-compiled function defined in simple.el.gz.

Signature

(shell-command COMMAND &optional OUTPUT-BUFFER ERROR-BUFFER)

Documentation

Execute string COMMAND in inferior shell; display output, if any.

With prefix argument, insert the COMMAND's output at point.

Interactively, prompt for COMMAND in the minibuffer. If shell-command-prompt-show-cwd is non-nil, show the current directory in the prompt.

If COMMAND ends in &, execute it asynchronously. The output appears in the buffer whose name is specified by shell-command-buffer-name-async. That buffer is in major mode specified by the variable async-shell-command-mode. You can also use async-shell-command that automatically adds &.

Otherwise, COMMAND is executed synchronously. The output appears in the buffer named by shell-command-buffer-name. If the output is short enough to display in the echo area (which is determined by the variables resize-mini-windows and max-mini-window-height), it is shown there, but it is nonetheless available in buffer named by shell-command-buffer-name even though that buffer is not automatically displayed.

To specify a coding system for converting non-ASCII characters in the shell command output, use C-x RET c (universal-coding-system-argument) before this command.

Noninteractive callers can specify coding systems by binding coding-system-for-read and coding-system-for-write.

The optional second argument OUTPUT-BUFFER, if non-nil, says to put the output in some other buffer. If OUTPUT-BUFFER is a buffer or buffer name, erase that buffer and insert the output there; a non-nil value of shell-command-dont-erase-buffer prevents the buffer from being erased. If OUTPUT-BUFFER is not a buffer and not nil (which happens interactively when the prefix argument is given), insert the output in current buffer after point leaving mark after it. This cannot be done asynchronously.

If OUTPUT-BUFFER is a buffer or buffer name different from the current buffer, instead of outputting at point in that buffer, the output will be appended at the end of that buffer.

The user option shell-command-dont-erase-buffer, which see, controls whether the output buffer is erased and where to put point after the shell command.

If the command terminates without error, but generates output, and you did not specify "insert it in the current buffer", the output can be displayed in the echo area or in its buffer. If the output is short enough to display in the echo area
(determined by the variable max-mini-window-height if
resize-mini-windows is non-nil), it is shown there. Otherwise, the buffer containing the output is displayed. Note that if shell-command-dont-erase-buffer is non-nil, the echo area could display more than just the output of the last command.

If there is output and an error, and you did not specify "insert it in the current buffer", a message about the error goes at the end of the output.

If the optional third argument ERROR-BUFFER is non-nil, it is a buffer or buffer name to which to direct the command's standard error output. If it is nil, error output is mingled with regular output. In an interactive call, the variable shell-command-default-error-buffer specifies the value of ERROR-BUFFER.

In Elisp, you will often be better served by calling call-process or start-process directly, since they offer more control and do not impose the use of a shell (with its need to quote arguments).

This function has :around advice: shell-command@shell-command-with-editor-mode.

View in manual

Probably introduced at or before Emacs version 19.31.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/simple.el.gz
(defun shell-command (command &optional output-buffer error-buffer)
  "Execute string COMMAND in inferior shell; display output, if any.
With prefix argument, insert the COMMAND's output at point.

Interactively, prompt for COMMAND in the minibuffer.
If `shell-command-prompt-show-cwd' is non-nil, show the current
directory in the prompt.

If COMMAND ends in `&', execute it asynchronously.
The output appears in the buffer whose name is specified
by `shell-command-buffer-name-async'.  That buffer is in major mode
specified by the variable `async-shell-command-mode'.  You can also use
`async-shell-command' that automatically adds `&'.

Otherwise, COMMAND is executed synchronously.  The output appears in
the buffer named by `shell-command-buffer-name'.  If the output is
short enough to display in the echo area (which is determined by the
variables `resize-mini-windows' and `max-mini-window-height'), it is
shown there, but it is nonetheless available in buffer named by
`shell-command-buffer-name' even though that buffer is not
automatically displayed.

To specify a coding system for converting non-ASCII characters
in the shell command output, use \\[universal-coding-system-argument] \
before this command.

Noninteractive callers can specify coding systems by binding
`coding-system-for-read' and `coding-system-for-write'.

The optional second argument OUTPUT-BUFFER, if non-nil,
says to put the output in some other buffer.
If OUTPUT-BUFFER is a buffer or buffer name, erase that buffer
and insert the output there; a non-nil value of
`shell-command-dont-erase-buffer' prevents the buffer from being
erased.  If OUTPUT-BUFFER is not a buffer and not nil (which happens
interactively when the prefix argument is given), insert the
output in current buffer after point leaving mark after it.  This
cannot be done asynchronously.

If OUTPUT-BUFFER is a buffer or buffer name different from the
current buffer, instead of outputting at point in that buffer,
the output will be appended at the end of that buffer.

The user option `shell-command-dont-erase-buffer', which see, controls
whether the output buffer is erased and where to put point after
the shell command.

If the command terminates without error, but generates output,
and you did not specify \"insert it in the current buffer\",
the output can be displayed in the echo area or in its buffer.
If the output is short enough to display in the echo area
\(determined by the variable `max-mini-window-height' if
`resize-mini-windows' is non-nil), it is shown there.
Otherwise, the buffer containing the output is displayed.
Note that if `shell-command-dont-erase-buffer' is non-nil,
the echo area could display more than just the output of the
last command.

If there is output and an error, and you did not specify \"insert it
in the current buffer\", a message about the error goes at the end
of the output.

If the optional third argument ERROR-BUFFER is non-nil, it is a buffer
or buffer name to which to direct the command's standard error output.
If it is nil, error output is mingled with regular output.
In an interactive call, the variable `shell-command-default-error-buffer'
specifies the value of ERROR-BUFFER.

In Elisp, you will often be better served by calling `call-process' or
`start-process' directly, since they offer more control and do not
impose the use of a shell (with its need to quote arguments)."

  (interactive
   (list
    (read-shell-command (if shell-command-prompt-show-cwd
                            (format-message "Shell command in `%s': "
                                            (abbreviate-file-name
                                             default-directory))
                          "Shell command: ")
                        nil nil
			(let ((filename
			       (cond
				(buffer-file-name)
				((eq major-mode 'dired-mode)
				 (dired-get-filename nil t)))))
			  (and filename (file-relative-name filename))))
    current-prefix-arg
    shell-command-default-error-buffer))
  ;; Look for a handler in case default-directory is a remote file name.
  (let ((handler
	 (find-file-name-handler (directory-file-name default-directory)
				 'shell-command)))
    (if handler
	(funcall handler 'shell-command command output-buffer error-buffer)
      (if (and output-buffer
               (not (string-match "[ \t]*&[ \t]*\\'" command))
               (or (eq output-buffer (current-buffer))
                   (and (stringp output-buffer) (eq (get-buffer output-buffer) (current-buffer)))
                   (not (or (bufferp output-buffer) (stringp output-buffer))))) ; Bug#39067
	  ;; Synchronous command with output in current buffer.
	  (let ((error-file
                 (and error-buffer
                      (make-temp-file
                       (expand-file-name "scor"
                                         (or small-temporary-file-directory
                                             temporary-file-directory))))))
	    (barf-if-buffer-read-only)
	    (push-mark nil t)
            (shell-command-save-pos-or-erase 'output-to-current-buffer)
	    ;; We do not use -f for csh; we will not support broken use of
	    ;; .cshrcs.  Even the BSD csh manual says to use
	    ;; "if ($?prompt) exit" before things that are not useful
	    ;; non-interactively.  Besides, if someone wants their other
	    ;; aliases for shell commands then they can still have them.
            (call-process-shell-command command nil (if error-file
                                                        (list t error-file)
                                                      t))
	    (when (and error-file (file-exists-p error-file))
              (when (< 0 (file-attribute-size (file-attributes error-file)))
                (with-current-buffer (get-buffer-create error-buffer)
                  (let ((pos-from-end (- (point-max) (point))))
                    (or (bobp)
                        (insert "\f\n"))
                    ;; Do no formatting while reading error file,
                    ;; because that can run a shell command, and we
                    ;; don't want that to cause an infinite recursion.
                    (format-insert-file error-file nil)
                    ;; Put point after the inserted errors.
                    (goto-char (- (point-max) pos-from-end)))
                  (display-buffer (current-buffer))))
	      (delete-file error-file))
	    ;; This is like exchange-point-and-mark, but doesn't
	    ;; activate the mark.  It is cleaner to avoid activation,
	    ;; even though the command loop would deactivate the mark
	    ;; because we inserted text.
	    (goto-char (prog1 (mark t)
			 (set-marker (mark-marker) (point)
				     (current-buffer)))))
	;; Output goes in a separate buffer.
	(if (string-match "[ \t]*&[ \t]*\\'" command)
	    ;; Command ending with ampersand means asynchronous.
            (let* ((_ (or (null output-buffer)
                          (bufferp output-buffer)
                          (stringp output-buffer)
                          (error "Asynchronous shell commands cannot output to current buffer")))
                   ;; Remove the ampersand and test if the command is
                   ;; not empty before creating a new buffer.
                   (command (substring command 0 (match-beginning 0)))
                   (_ (or (not (string= command ""))
                          (error "Empty asynchronous command")))
                   (buffer (get-buffer-create
                            (or output-buffer shell-command-buffer-name-async)))
                   (bname (buffer-name buffer))
                   (proc (get-buffer-process buffer))
                   (directory default-directory))
	      ;; Ask the user what to do with already running process.
	      (when proc
		(cond
		 ((eq async-shell-command-buffer 'confirm-kill-process)
		  ;; If will kill a process, query first.
                  (shell-command--same-buffer-confirm "Kill it")
		  (kill-process proc))
		 ((eq async-shell-command-buffer 'confirm-new-buffer)
		  ;; If will create a new buffer, query first.
                  (shell-command--same-buffer-confirm "Use a new buffer")
                  (setq buffer (generate-new-buffer bname)))
		 ((eq async-shell-command-buffer 'new-buffer)
		  ;; It will create a new buffer.
                  (setq buffer (generate-new-buffer bname)))
		 ((eq async-shell-command-buffer 'confirm-rename-buffer)
		  ;; If will rename the buffer, query first.
                  (shell-command--same-buffer-confirm "Rename it")
		  (with-current-buffer buffer
		    (rename-uniquely))
                  (setq buffer (get-buffer-create bname)))
		 ((eq async-shell-command-buffer 'rename-buffer)
		  ;; It will rename the buffer.
		  (with-current-buffer buffer
		    (rename-uniquely))
                  (setq buffer (get-buffer-create bname)))))
	      (with-current-buffer buffer
                (shell-command-save-pos-or-erase)
		(setq default-directory directory)
                ;; There could be left connection-local values.  (Bug#76888)
                (kill-local-variable 'shell-file-name)
                (kill-local-variable 'shell-command-switch)
                (require 'shell)
                (let ((process-environment
                       (append
                        (and (natnump async-shell-command-width)
                             (list
                              (format "COLUMNS=%d"
                                      async-shell-command-width)))
                        (comint-term-environment)
                        process-environment)))
		  (setq proc
			(start-process-shell-command "Shell" buffer command)))
		(setq mode-line-process '(":%s"))
                (funcall async-shell-command-mode)
                (setq-local revert-buffer-function
                            (lambda (&rest _)
                              (async-shell-command command buffer)))
                (set-process-sentinel proc #'shell-command-sentinel)
		;; Use the comint filter for proper handling of
		;; carriage motion (see comint-inhibit-carriage-motion).
                (set-process-filter proc #'comint-output-filter)
                (if async-shell-command-display-buffer
                    ;; Display buffer immediately.
                    (display-buffer buffer '(nil (allow-no-window . t)))
                  ;; Defer displaying buffer until first process output.
                  ;; Use disposable named advice so that the buffer is
                  ;; displayed at most once per process lifetime.
                  (let ((nonce (make-symbol "nonce")))
                    (add-function :before (process-filter proc)
                                  (lambda (proc _string)
                                    (let ((buf (process-buffer proc)))
                                      (when (buffer-live-p buf)
                                        (remove-function (process-filter proc)
                                                         nonce)
                                        (display-buffer buf '(nil (allow-no-window . t))))))
                                  `((name . ,nonce)))))))
	  ;; Otherwise, command is executed synchronously.
	  (shell-command-on-region (point) (point) command
				   output-buffer nil error-buffer))))))