Subject: Re: bug#31601: Dired/Wdired: Play nicely with recursive list of files and directories.

From: Tino Calancha <[email-masked]>
Date: Sat, 26 May 2018 18:02:26 +0900

Keith David Bershatsky <[email-masked]> writes:

> I occasionally have the need to rename files and directories that are recursively located.  I create a dired-mode buffer as follows:
>
>     (dired (directory-files-recursively "/path/to/directory" "" 'include-directories))
>
> Wdired:  The first problem is that `wdired-get-filename' needs to be modified so that it handles absolute paths differently than relative filenames.

> Dired:  The second problem is a dired-mode problem in that the `dired-directory' variable is not updated when renaming a file

Thank you for your report Keith!
You are right, it looks annoying.

Though I haven't arrived with an ideal solution, following
are two ways how I would try to perform a similar task.

I)
If you are lucky and "sh" points to a shell that
supports globstar (zsh, fish), or if you are using dired
via `em-ls', then you can do:
M-x dired /path/to/directory/**/* RET
;; Now both, wdired and `dired-do-rename' works fine.

[If you are using bash or ksh, that support globstar but
disable it by default, then you might be interestd in my
proposal in Bug#31495: it gives the chance to enable such
feature on dired via an user option.]

II)
Another way could be to use a command of the `find-dired' family:
M-x find-name-dired /path/to/directory/ RET * RET
;; I just noticed that wdired resets `revert-buffer-function' also for
;; these dired buffers.  IMO it shouldn't, so I would propose
;; something like this:
--8<-----------------------------cut here---------------start------------->8---
commit 58842a20f570d32f5d3f90aced8f0e8c1b1535a7
Author: Tino Calancha <[email-masked]>
Date:   Sat May 26 17:39:29 2018 +0900

    Preserve revert-buffer-function on find-dired buffers
    
    * lisp/wdired.el (wdired-find-dired-buffer-p): New predicate.
    (wdired-change-to-wdired-mode, wdired-change-to-dired-mode):
    Preserve `revert-buffer-function' on dired buffers created
    with `find-dired' commands.

diff --git a/lisp/wdired.el b/lisp/wdired.el
index bb60e77776..de5b327d75 100644
--- a/lisp/wdired.el
+++ b/lisp/wdired.el
@@ -228,6 +228,12 @@ wdired-mode
   (error "This mode can be enabled only by `wdired-change-to-wdired-mode'"))
 (put 'wdired-mode 'mode-class 'special)
 
+(defun wdired-find-dired-buffer-p ()
+  "Return non-nil if the dired buffer comes from a `find-dired' command."
+  (save-excursion
+    (goto-char (point-min))
+    (forward-line 1)
+    (re-search-forward (format "^\\s-*%s " find-program) nil t)))
 
 ;;;###autoload
 (defun wdired-change-to-wdired-mode ()
@@ -257,7 +263,8 @@ wdired-change-to-wdired-mode
   (add-hook 'kill-buffer-hook 'wdired-check-kill-buffer nil t)
   (setq major-mode 'wdired-mode)
   (setq mode-name "Editable Dired")
-  (setq revert-buffer-function 'wdired-revert)
+  (unless (wdired-find-dired-buffer-p)
+    (setq revert-buffer-function 'wdired-revert))
   ;; I temp disable undo for performance: since I'm going to clear the
   ;; undo list, it can save more than a 9% of time with big
   ;; directories because setting properties modify the undo-list.
@@ -363,7 +370,8 @@ wdired-change-to-dired-mode
   (setq mode-name "Dired")
   (dired-advertise)
   (remove-hook 'kill-buffer-hook 'wdired-check-kill-buffer t)
-  (set (make-local-variable 'revert-buffer-function) 'dired-revert))
+  (unless (wdired-find-dired-buffer-p)
+    (set (make-local-variable 'revert-buffer-function) 'dired-revert)))

 (defun wdired-abort-changes ()
--8<-----------------------------cut here---------------end--------------->8---
In GNU Emacs 27.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.22.11)
 of 2018-05-26 built on calancha-pc
Repository revision: 66c9ab90d5f8b566467549bf1d48c936bc6d296b