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 "&")
         ""))))