Function: dired-shell-stuff-it
dired-shell-stuff-it is a byte-compiled function defined in
dired-aux.el.gz.
Signature
(dired-shell-stuff-it COMMAND FILE-LIST ON-EACH &optional RAW-ARG)
Source Code
;; Defined in /usr/src/emacs/lisp/dired-aux.el.gz
(defun dired-shell-stuff-it (command file-list on-each &optional _raw-arg)
;; "Make up a shell command line from COMMAND and FILE-LIST.
;; If ON-EACH is t, COMMAND should be applied to each file, else
;; simply concat all files and apply COMMAND to this.
;; FILE-LIST's elements will be quoted for the shell."
;; Might be redefined for smarter things and could then use RAW-ARG
;; (coming from interactive P and currently ignored) to decide what to do.
;; Smart would be a way to access basename or extension of file names.
(let* ((in-background (string-match "[ \t]*&[ \t]*\\'" command))
(command (if in-background
(substring command 0 (match-beginning 0))
command))
(sequentially (string-match "[ \t]*;[ \t]*\\'" command))
(command (if sequentially
(substring command 0 (match-beginning 0))
command))
(parallel-in-background
(and in-background (not sequentially) (not (eq system-type 'ms-dos))))
(w32-shell (and (fboundp 'w32-shell-dos-semantics)
(w32-shell-dos-semantics)))
(file-remote (file-remote-p default-directory))
;; The way to run a command in background in Windows shells
;; is to use the START command. The /B switch means not to
;; create a new window for the command.
(cmd-prefix (if (and w32-shell (not file-remote)) "start /b " ""))
;; Windows shells don't support chaining with ";", they use
;; "&" instead.
(cmd-sep (if (and (or (not w32-shell) file-remote)
(not parallel-in-background))
"; " "& "))
(stuff-it
(if (dired--star-or-qmark-p command nil 'keep)
(lambda (x)
(let ((retval (concat cmd-prefix command)))
(while (dired--star-or-qmark-p retval nil)
(setq retval (replace-match x t t retval 2)))
retval))
(lambda (x) (concat cmd-prefix command dired-mark-separator x)))))
;; If a file name starts with "-", add a "./" to avoid the command
;; interpreting it as a command line switch.
(setq file-list (mapcar (lambda (file)
(if (string-match "\\`-" file)
(concat "./" file)
file))
file-list))
(concat
(cond
(on-each
(format "%s%s"
(mapconcat stuff-it (mapcar #'shell-quote-argument file-list)
cmd-sep)
;; POSIX shells running a list of commands in the background
;; (LIST = cmd_1 & [cmd_2 & ... cmd_i & ... cmd_N &])
;; return once cmd_N ends, i.e., the shell does not
;; wait for cmd_i to finish before executing cmd_i+1.
;; That means, running (shell-command LIST) may not show
;; the output of all the commands (Bug#23206).
;; Add 'wait' to force those POSIX shells to wait until
;; all commands finish.
(or (and parallel-in-background (not w32-shell)
" & wait")
"")))
(t
(let ((files (mapconcat #'shell-quote-argument
file-list dired-mark-separator)))
(when (cdr file-list)
(setq files (concat dired-mark-prefix files dired-mark-postfix)))
(concat
(funcall stuff-it files)
;; Be consistent in how we treat inputs to commands -- do
;; the same here as in the `on-each' case.
(if (and in-background (not w32-shell))
" & wait"
"")))))
(or (and in-background "& ")
""))))