unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* compare-directories
@ 2003-08-29  6:36 Juri Linkov
  2003-08-30  3:10 ` compare-directories Richard Stallman
  0 siblings, 1 reply; 2+ messages in thread
From: Juri Linkov @ 2003-08-29  6:36 UTC (permalink / raw)


Many file managers (e.g. GNU Midnight Commander and other
"Commander"-like file managers) provide the functionality to mark
different files in two panels based on their attributes (time, size).
I would like to propose one function that adds same functionality to
Emacs dired.  It could be added either to dired-aux.el (after
`dired-diff') or to dired-x.el (after `dired-mark-sexp').

This function compares file attributes of files in the current
directory with file attributes in second directory using given
predicate on pairs of files with the same name.  It does this
by applying the mutual set-difference operation on two lists of files
with their attributes from two dired buffers.  Files for which
predicate returns non-nil are marked by mark character.

The implementation of this function is terse and elegant, but
at the cost of using function `set-difference' from cl-seq.el.
I followed the recent discussion about extracting useful functions
from the cl package.  I think that set functions should be extracted
in the first place.  Or maybe, it makes sense to rewrite these functions
from scratch to make them cl-free?

================================================================
(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.

PREDICATE is a lisp expression that can refer to the following symbols:

    size1, size2   - file size in bytes
    mtime1, mtime2 - last modification time in seconds
    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= (nth 8 fa1) (nth 8 fa2))) - mark files with different modes
    (not (and (= (nth 2 fa1) (nth 2 fa2))   - mark files with different UID
              (= (nth 3 fa1) (nth 3 fa2))))   and GID."
  (interactive
   (list (read-file-name (format "Compare %s with: "
				 (dired-current-directory))
			 (dired-dwim-target-directory))
	 (read-minibuffer "Mark if (lisp expr): ")))
  (let* ((dir1 (dired-current-directory))
         (file-alist1 (dired-files-attributes dir1))
         (file-alist2 (dired-files-attributes dir2))
	 (file-list1 (mapcar
                      (lambda (f) (cadr f))
                      (set-difference
                       file-alist1 file-alist2
                       :test '(lambda (file1 file2)
                                (let* ((fa1 (caddr file1))
                                       (fa2 (caddr file2))
                                       (size1 (nth 7 fa1))
                                       (size2 (nth 7 fa2))
                                       (mtime1 (float-time (nth 5 fa1)))
                                       (mtime2 (float-time (nth 5 fa2))))
                                  (and
                                   (equal (car file1) (car file2))
                                   (not (eval predicate))))))))
	 (file-list2 (mapcar
                      (lambda (f) (cadr f))
                      (set-difference
                       file-alist2 file-alist1
                       :test '(lambda (file1 file2)
                                (let* ((fa1 (caddr file1))
                                       (fa2 (caddr file2))
                                       (size1 (nth 7 fa1))
                                       (size2 (nth 7 fa2))
                                       (mtime1 (float-time (nth 5 fa1)))
                                       (mtime2 (float-time (nth 5 fa2))))
                                  (and
                                   (equal (car file1) (car file2))
                                   (not (eval 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 files, in dir2: %s files"
             (length file-list1)
             (length file-list2))))

(defun dired-files-attributes (dir)
  "Return a list of all file names and attributes from DIR.
List has a form of (file-name full-file-name (attribute-list))"
  (mapcar
   (lambda (file-name)
     (let ((full-file-name (expand-file-name file-name dir)))
       (list file-name
             full-file-name
             (file-attributes full-file-name))))
   (directory-files dir)))
================================================================

-- 
http://www.jurta.org/emacs/

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: compare-directories
  2003-08-29  6:36 compare-directories Juri Linkov
@ 2003-08-30  3:10 ` Richard Stallman
  0 siblings, 0 replies; 2+ messages in thread
From: Richard Stallman @ 2003-08-30  3:10 UTC (permalink / raw)
  Cc: emacs-devel

This sounds like a good feature.  I can install it when your
papers come.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2003-08-30  3:10 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-08-29  6:36 compare-directories Juri Linkov
2003-08-30  3:10 ` compare-directories Richard Stallman

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).