changeset 42676:24e0ac83a078

(dired-shell-stuff-it): Substitute for * or ? only when they are surrounded by whitespace. Use dired-mark-separator when adding one file name to a command. (dired-do-shell-command): Verify that * is surrounded by whitespace. Ask for confirmation if * or ? is not surrounded by whitespace. (dired-bunch-files): Re-reverse the partial file list when it is used.
author Richard M. Stallman <rms@gnu.org>
date Sat, 12 Jan 2002 20:14:25 +0000
parents 640c0fcaebf1
children 449f96bbb6d0
files lisp/dired-aux.el
diffstat 1 files changed, 57 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/dired-aux.el	Sat Jan 12 16:01:51 2002 +0000
+++ b/lisp/dired-aux.el	Sat Jan 12 20:14:25 2002 +0000
@@ -154,7 +154,7 @@
 	;; and this file won't fit in the length limit, process now.
 	(if (and pending (> (+ thislength pending-length) max))
 	    (setq failures
-		  (nconc (apply function (append args pending))
+		  (nconc (apply function (append args (nreverse pending)))
 			 failures)
 		  pending nil
 		  pending-length 0))
@@ -164,7 +164,7 @@
 	(setq pending files)
 	(setq pending-length (+ thislength pending-length))
 	(setq files rest)))
-    (nconc (apply function (append args pending))
+    (nconc (apply function (append args (nreverse pending)))
 	   failures)))
 
 ;;;###autoload
@@ -316,22 +316,30 @@
 the next ARG files are used.  Just \\[universal-argument] means the current file.
 The prompt mentions the file(s) or the marker, as appropriate.
 
-If there is output, it goes to a separate buffer.
+If there is a `*' in COMMAND, surrounded by whitespace, this runs
+COMMAND just once with the entire file list substituted there.
 
-Normally the command is run on each file individually.
-However, if there is a `*' in the command then it is run
-just once with the entire file list substituted there.
+If there is no `*', but there is a `?' in COMMAND, surrounded by
+whitespace, this runs COMMAND on each file individually with the
+file name substituted for `?'.
+
+Otherwise, this runs COMMAND on each file individually with the
+file name added at the end of COMMAND (separated by a space).
 
-If there is no `*', but a `?' in the command then it is still run
-on each file individually but with the filename substituted there
-instead of at the end of the command.
+`*' and `?' when not surrounded by whitespace have no special
+significance for `dired-do-shell-command', and are passed through
+normally to the shell, but you must confirm first.  To pass `*' by
+itself to the shell as a wildcard, type `*""'.
+
+If COMMAND produces output, it goes to a separate buffer.
 
-No automatic redisplay of dired buffers is attempted, as there's no
-telling what files the command may have changed.  Type
-\\[dired-do-redisplay] to redisplay the marked files.
+This feature does not try to redisplay Dired buffers afterward, as
+there's no telling what files COMMAND may have changed.
+Type \\[dired-do-redisplay] to redisplay the marked files.
 
-The shell command has the top level directory as working directory, so
-output files usually are created there instead of in a subdir.
+When COMMAND runs, its working directory is the top-level directory of
+the Dired buffer, so output files usually are created there instead of
+in a subdir.
 
 In a noninteractive call (from Lisp code), you must specify
 the list of file names explicitly with the FILE-LIST argument."
@@ -347,18 +355,28 @@
 				files)
       current-prefix-arg
       files)))
-  (let* ((on-each (not (string-match "\\*" command))))
-    (if on-each
-	(dired-bunch-files
-	 (- 10000 (length command))
-	 (function (lambda (&rest files)
-		     (dired-run-shell-command
-		      (dired-shell-stuff-it command files t arg))))
-	 nil
-	 file-list)
-      ;; execute the shell command
-      (dired-run-shell-command
-       (dired-shell-stuff-it command file-list nil arg)))))
+  (let* ((on-each (not (string-match "\\(^\\|[ \t]\\)\\*\\([ \t]\\|$\\)" command)))
+	 (subst (not (string-match "\\(^\\|[ \t]\\)\\?\\([ \t]\\|$\\)" command)))
+	 (star (not (string-match "\\*" command)))
+	 (qmark (not (string-match "\\?" command))))
+    ;; Get confirmation for wildcards that may have been meant
+    ;; to control substitution of a file name or the file name list.
+    (if (cond ((and star (not on-each))
+	       (y-or-n-p "Confirm--do you mean to use `*' as a wildcard? "))
+	      ((and qmark (not subst))
+	       (y-or-n-p "Confirm--do you mean to use `?' as a wildcard? "))
+	      (t))
+	(if on-each
+	    (dired-bunch-files
+	     (- 10000 (length command))
+	     (function (lambda (&rest files)
+			 (dired-run-shell-command
+			  (dired-shell-stuff-it command files t arg))))
+	     nil
+	     file-list)
+	  ;; execute the shell command
+	  (dired-run-shell-command
+	   (dired-shell-stuff-it command file-list nil arg))))))
 
 ;; Might use {,} for bash or csh:
 (defvar dired-mark-prefix ""
@@ -376,25 +394,23 @@
 ;; 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.
-;; See dired-trns.el for an approach to this.
-  ;; Bug: There is no way to quote a * or a ?
-  ;; On the other hand, you can never accidentally get a * or a ? into
-  ;; your cmd.
   (let ((stuff-it
-	 (cond ((string-match "\\*" command)
-		(function (lambda (x)
-			    (dired-replace-in-string "\\*" x command))))
-	       ((string-match "\\?" command)
-		(function (lambda (x)
-			     (dired-replace-in-string "\\?" x command))))
-	       (t (function (lambda (x) (concat command " " x)))))))
+	 (cond ((string-match "\\(^\\|[ \t]\\)\\*\\([ \t]\\|$\\)" command)
+		(lambda (x)
+		  (string-match "\\(^\\|[ \t]\\)\\(\\*\\)\\([ \t]\\|$\\)" command)
+		  (replace-match x t t command 2)))
+	       ((string-match "\\(^\\|[ \t]\\)\\?\\([ \t]\\|$\\)" command)
+		(lambda (x)
+		  (string-match "\\(^\\|[ \t]\\)\\(\\?\\)\\([ \t]\\|$\\)" command)
+		  (replace-match x t t command 2)))
+	       (t (lambda (x) (concat command dired-mark-separator x))))))
     (if on-each
 	(mapconcat stuff-it (mapcar 'shell-quote-argument file-list) ";")
-      (let ((fns (mapconcat 'shell-quote-argument
-			    file-list dired-mark-separator)))
+      (let ((files (mapconcat 'shell-quote-argument
+			      file-list dired-mark-separator)))
 	(if (> (length file-list) 1)
-	    (setq fns (concat dired-mark-prefix fns dired-mark-postfix)))
-	(funcall stuff-it fns)))))
+	    (setq files (concat dired-mark-prefix files dired-mark-postfix)))
+	(funcall stuff-it files)))))
 
 ;; This is an extra function so that it can be redefined by ange-ftp.
 (defun dired-run-shell-command (command)