In DiredMode, I sometimes feel the need to open asynchronous commands on one file, for example for displaying a pdf. I find it better not to be obliged to type the ? or the * for this, so I can do:
C-u ! xpdf & RET instead of C-u ! xpdf ? RET.
To do that, I change slightly ‘dired-shell-stuff-it’:
(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* ((async "")
(stuff-it
(progn
(when (string-match "[ \t]*&[ \t]*\\'" command)
(setq async " &")
(setq command (substring command 0 (match-beginning 0))))
(if (or (string-match dired-star-subst-regexp command)
(string-match dired-quark-subst-regexp command))
(lambda (x)
(let ((retval command))
(while (string-match
"\\(^\\|[ \t]\\)\\([*?]\\)\\([ \t]\\|$\\)" retval)
(setq retval (replace-match x t t retval 2)))
retval))
(lambda (x) (concat command dired-mark-separator x async))))))
(if on-each
(mapconcat stuff-it (mapcar 'shell-quote-argument file-list) ";")
(let ((files (mapconcat 'shell-quote-argument
file-list dired-mark-separator)))
(if (> (length file-list) 1)
(setq files (concat dired-mark-prefix files dired-mark-postfix)))
(funcall stuff-it files)))))See also DiredTweaks