Function: dired-compare-directories

dired-compare-directories is an autoloaded, interactive and byte-compiled function defined in dired-aux.el.gz.

Signature

(dired-compare-directories DIR2 PREDICATE)

Documentation

Mark files with different file attributes in two dired buffers.

Compare file attributes of files in the current directory with file attributes in directory DIR2 using PREDICATE on pairs of files with the same name. Mark files for which PREDICATE returns non-nil. Mark files with different names if PREDICATE is nil (or interactively with empty input at the predicate prompt).

PREDICATE is a Lisp expression that can refer to the following variables:

    size1, size2 - file size in bytes
    mtime1, mtime2 - last modification time in seconds, as a float
    fa1, fa2 - list of file attributes
                     returned by function file-attributes

    where 1 refers to attribute of file in the current dired buffer
    and 2 to attribute of file in second dired buffer.

Examples of PREDICATE:

    (> mtime1 mtime2) - mark newer files
    (not (= size1 size2)) - mark files with different sizes
    (not (string= (file-attribute-modes fa1) - mark files with different modes
                  (file-attribute-modes fa2)))
    (not (and (= (file-attribute-user-id fa1) - mark files with different UID
                 (file-attribute-user-id fa2))
              (= (file-attribute-group-id fa1) - and GID.
                 (file-attribute-group-id fa2))))

If the region is active in Transient Mark mode, mark files only in the active region if dired-mark-region is non-nil.

Probably introduced at or before Emacs version 22.1.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/dired-aux.el.gz
;;;###autoload
(defun dired-compare-directories (dir2 predicate)
  "Mark files with different file attributes in two dired buffers.
Compare file attributes of files in the current directory
with file attributes in directory DIR2 using PREDICATE on pairs of files
with the same name.  Mark files for which PREDICATE returns non-nil.
Mark files with different names if PREDICATE is nil (or interactively
with empty input at the predicate prompt).

PREDICATE is a Lisp expression that can refer to the following variables:

    size1, size2   - file size in bytes
    mtime1, mtime2 - last modification time in seconds, as a float
    fa1, fa2       - list of file attributes
                     returned by function `file-attributes'

    where 1 refers to attribute of file in the current dired buffer
    and 2 to attribute of file in second dired buffer.

Examples of PREDICATE:

    (> mtime1 mtime2) - mark newer files
    (not (= size1 size2)) - mark files with different sizes
    (not (string= (file-attribute-modes fa1)  - mark files with different modes
                  (file-attribute-modes fa2)))
    (not (and (= (file-attribute-user-id fa1) - mark files with different UID
                 (file-attribute-user-id fa2))
              (= (file-attribute-group-id fa1) - and GID.
                 (file-attribute-group-id fa2))))

If the region is active in Transient Mark mode, mark files
only in the active region if `dired-mark-region' is non-nil."
  (interactive
   (list
    (let* ((target-dir (dired-dwim-target-directory))
	   (defaults (dired-dwim-target-defaults nil target-dir)))
      (minibuffer-with-setup-hook
	  (lambda ()
            (setq-local minibuffer-default-add-function nil)
	    (setq minibuffer-default defaults))
	(read-directory-name (format "Compare %s with: "
				     (dired-current-directory))
			     target-dir target-dir t)))
    (read-from-minibuffer "Mark if (lisp expr or RET): " nil nil t nil "nil")))
  (let* ((dir1 (dired-current-directory))
         (file-alist1 (dired-files-attributes dir1))
         (file-alist2 (dired-files-attributes dir2))
	 file-list1 file-list2)
    (setq file-alist1 (delq (assoc "." file-alist1) file-alist1))
    (setq file-alist1 (delq (assoc ".." file-alist1) file-alist1))
    (setq file-alist2 (delq (assoc "." file-alist2) file-alist2))
    (setq file-alist2 (delq (assoc ".." file-alist2) file-alist2))
    (setq file-list1 (mapcar
		      #'cadr
                      (dired-file-set-difference
                       file-alist1 file-alist2
		       predicate))
	  file-list2 (mapcar
		      #'cadr
                      (dired-file-set-difference
                       file-alist2 file-alist1
		       predicate)))
    (dired-fun-in-all-buffers
     dir1 nil
     (lambda ()
       (dired-mark-if
        (member (dired-get-filename nil t) file-list1) nil)))
    (dired-fun-in-all-buffers
     dir2 nil
     (lambda ()
       (dired-mark-if
        (member (dired-get-filename nil t) file-list2) nil)))
    (message "Marked in dir1: %s, in dir2: %s"
             (format-message (ngettext "%d file" "%d files" (length file-list1))
                             (length file-list1))
             (format-message (ngettext "%d file" "%d files" (length file-list2))
                             (length file-list2)))))