20

I am experimenting with ediff-directories, but I am not sure I am using it correctly.

I read in the documentation that, once I supply two directories to ediff-directories, if I press == Emacs compares them recursively.

However, if I press == I only get folders with = signs (meaning that the two folders have identical contents) on the level where I run the command. If I want to see which folders have = signs at deeper levels in the folder hierarchy, I need to re-run the == command at each level.

How can I tell emacs to go recursively all the way to the leaves so that I can see all the differences in the directory difference buffer (accessible via the keyboard command D)?

If anybody knows of a tutorial on how to use ediff-directories (other than the official documentation), I would be highly interested.


Also, if I want to exit a session group (comparison of folders at one level), but I have sessions open for deeper levels, if I press q (quit this session group), Emacs complains with the messaage:

This sesssion group has active sessions---cannot exit

How can I exit session groups without exiting the sub-sessions one by one?

2

4 Answers 4

9

There is ztree package available from Melpa which supports recursive directory tree comparison: M-x ztree-diff using GNU diff utilities to compare corresponding files.

If you use use-package then to install and configure ztree package, add to your .emacs:

;; ** recursive directory tree comparison: M-x ztree-diff
(use-package ztree
  :ensure t) ; needs GNU diff utility
7

I have used M-x dired-compare-directories, but there is also EdiffTrees, which might serve you better in the situation you describe.

1
  • There's also a = bind if you're already in Dired. Oct 26, 2022 at 4:14
4

I also needed this feature and came up with the following. The function ediff-directories-recursive works like ediff-directories but recurses into sub-directories.

The magic behind that is temporarily replacing the built-in directory-files by a self-made directory-files-recursive before calling ediff-directories.

(eval
 (let ((directory-files-original (symbol-function 'directory-files)))
   `(defun directory-files-recursive (directory &optional full match nosort)
      "Like `directory-files' but recurses into subdirectories. Does not follow symbolic links."
      (let* ((prefix (or (and full "") directory))
         dirs
         files)
    (mapc (lambda (p)
        (let ((fullname (if full p (concat prefix "/" p))))
          (when (and (file-directory-p fullname)
                 (null (or (string-match "\\(^\\|/\\).$" p)
                       (string-match "\\(^\\|/\\)..$" p)
                       (file-symlink-p fullname))))
            (setq dirs (cons p dirs)))))
          (funcall ,directory-files-original directory full nil nosort))
    (setq dirs (nreverse dirs))
    (mapc (lambda (p)
        (when (null (file-directory-p (if full p (concat prefix "/" p))))
          (setq files (cons p files))))
          (funcall ,directory-files-original directory full match nosort))
    (setq files (nreverse files))
    (mapc (lambda (d)
        (setq files
              (append files
                  (if full
                  (apply 'directory-files-recursive (list d full match nosort))
                (mapcar (lambda (n)
                      (concat d "/" n))
                    (apply 'directory-files-recursive (list (concat prefix "/" d) full match nosort)))))))
          dirs)
    files))))

(eval
 `(defun ediff-directories-recursive (dir1 dir2 regexp)
    "Like `ediff-directories' but recurses into sub-directories. Does not follow symbolic links."
    ,(interactive-form (symbol-function 'ediff-directories))
    (let ((directory-files-original (symbol-function 'directory-files)))
      (unwind-protect
      (progn
        (fset 'directory-files (symbol-function 'directory-files-recursive))
        (ediff-directories dir1 dir2 regexp)
        (fset 'directory-files directory-files-original))))))
1
  • I did eval-buffer and got this: Debugger entered--Lisp error: (wrong-type-argument symbolp (autoload "ediff" 890739 t nil)) interactive-form((autoload "ediff" 890739 t nil)) Any suggestion?
    – nephewtom
    Aug 25, 2015 at 10:09
1

Wanted to add to the ztree recommendation above; ztree is awesome. For those sitting on the fence, here is a screenshot..enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .