The EdiffTrees package is a simple frontend to EdiffMode to allow a simpler comparison of two similar directory trees.

I wrote this package because I often need to compare two different versions of the same directory tree and ediff-directories is not very helpful in this case. Specially when the directory trees to compare are deep and only a few files have changed.

For further instructions, please see the comentary in the file.


Any comments are welcomed, of course.

There seems to be something wrong with the link above.

Somebody uploaded a file instead of just pasting the elisp into the text area… – AlexSchroeder

Oops, I’ve fixed that with the update to a new version of the package.

I did something similar with the concept of secondary project roots. The example code is pasted in EdiffMode. I shall have a play with your mode 😊


i’ve been looking for this functionality for a long time. getting “function definition is void: eql” errors on diffs (everything i’ve tried so far), even for simple directories that only differ in one line of 1 file. any thoughts ? using emacs 21.2.1


I’d love a recursive directory diff in Emacs that presented a view of two dired buffers side by side, above two file buffers. I’d like to filter the dired buffers in various ways: (a) show all files, (b) show only differing files, (c) show only files added on the lhs/rhs. The file buffers should use ediff-mode.

Even better would be a three-way diff/merge with three file and dired buffers similar to the two way comparison case. – MatthewLMcClure

Thank you for writing this tool. It was handy for a task I just had and have encountered previously!

ediff-trees-examine-next-regexp is less convenient than it could be. I’d prefer the ediff-directories behavior of querying for a regular expression to match against filenames rather than constantly invoking ediff-trees-examine-next-regexp and giving the same regexp each time. (Even though I can recall the regexp from history, it’s awkward).

A control window, like ediff’s own, that provides the ability to navigate among the changed files, would be helpful, too. That is, having a window that permits jumping to the first, last, previous, next, or numbered file pair, like ediff permits navigating differences for a pair, would make the usage clearer. Thus, one would select a pair to compare, ediff-trees would run ediff, one would close ediff after comparing the files, then one would select the next pair to compare.


Comparing directories recursively in Emacs, even with a filter

Comes from http://unix.stackexchange.com/questions/27128/comparing-directories-in-emacs/152645#152645

Thanks to the author Tobias

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.

 (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))
    (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)))))))

 `(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)))
        (fset 'directory-files (symbol-function 'directory-files-recursive))
        (ediff-directories dir1 dir2 regexp)
        (fset 'directory-files directory-files-original))))))