aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman2003-12-01 01:56:19 +0000
committerRichard M. Stallman2003-12-01 01:56:19 +0000
commitd1c553c832d66677f2c1bd6d4e6394275cbe25e6 (patch)
tree6fbd0d036c888f68c3de5a49f49dc864d1f20e10
parent2a75d75d3fb2ed0da8031f0de912b1694ee1be1d (diff)
downloademacs-d1c553c832d66677f2c1bd6d4e6394275cbe25e6.tar.gz
emacs-d1c553c832d66677f2c1bd6d4e6394275cbe25e6.zip
(dired-do-query-replace-regexp): Report files visited read-only.
(dired-compare-directories): New command. (dired-file-set-difference, dired-files-attributes): New functions.
-rw-r--r--lisp/dired-aux.el100
1 files changed, 100 insertions, 0 deletions
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index ab3b65abac0..d12410afae5 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -88,6 +88,101 @@ With prefix arg, prompt for argument SWITCHES which is options for `diff'."
88 nil)) 88 nil))
89 (diff-backup (dired-get-filename) switches)) 89 (diff-backup (dired-get-filename) switches))
90 90
91(defun dired-compare-directories (dir2 predicate)
92 "Mark files with different file attributes in two dired buffers.
93Compare file attributes of files in the current directory
94with file attributes in directory DIR2 using PREDICATE on pairs of files
95with the same name. Mark files for which PREDICATE returns non-nil.
96
97PREDICATE is a Lisp expression that can refer to the following variables:
98
99 size1, size2 - file size in bytes
100 mtime1, mtime2 - last modification time in seconds, as a float
101 fa1, fa2 - list of file attributes
102 returned by function `file-attributes'
103
104 where 1 refers to attribute of file in the current dired buffer
105 and 2 to attribute of file in second dired buffer.
106
107Examples of PREDICATE:
108
109 (> mtime1 mtime2) - mark newer files
110 (not (= size1 size2)) - mark files with different sizes
111 (not (string= (nth 8 fa1) (nth 8 fa2))) - mark files with different modes
112 (not (and (= (nth 2 fa1) (nth 2 fa2)) - mark files with different UID
113 (= (nth 3 fa1) (nth 3 fa2)))) and GID."
114 (interactive
115 (list (read-file-name (format "Compare %s with: "
116 (dired-current-directory))
117 (dired-dwim-target-directory))
118 (read-minibuffer "Mark if (lisp expr): ")))
119 (let* ((dir1 (dired-current-directory))
120 (file-alist1 (dired-files-attributes dir1))
121 (file-alist2 (dired-files-attributes dir2))
122 (file-list1 (mapcar
123 'cadr
124 (dired-file-set-difference
125 file-alist1 file-alist2
126 predicate)))
127 (file-list2 (mapcar
128 'cadr
129 (dired-file-set-difference
130 file-alist2 file-alist1
131 predicate))))
132 (dired-fun-in-all-buffers
133 dir1 nil
134 (lambda ()
135 (dired-mark-if
136 (member (dired-get-filename nil t) file-list1) nil)))
137 (dired-fun-in-all-buffers
138 dir2 nil
139 (lambda ()
140 (dired-mark-if
141 (member (dired-get-filename nil t) file-list2) nil)))
142 (message "Marked in dir1: %s files, in dir2: %s files"
143 (length file-list1)
144 (length file-list2))))
145
146(defun dired-file-set-difference (list1 list2 predicate)
147 "Combine LIST1 and LIST2 using a set-difference operation.
148The result list contains all file items that appear in LIST1 but not LIST2.
149This is a non-destructive function; it makes a copy of the data if necessary
150to avoid corrupting the original LIST1 and LIST2.
151PREDICATE (see `dired-compare-directories') is an additional match
152condition. Two file items are considered to match if they are equal
153*and* PREDICATE evaluates to t."
154 (if (or (null list1) (null list2))
155 list1
156 (let (res)
157 (dolist (file1 list1)
158 (unless (let ((list list2))
159 (while (and list
160 (not (let* ((file2 (car list))
161 (fa1 (caddr file1))
162 (fa2 (caddr file2))
163 (size1 (nth 7 fa1))
164 (size2 (nth 7 fa2))
165 (mtime1 (float-time (nth 5 fa1)))
166 (mtime2 (float-time (nth 5 fa2))))
167 (and
168 (equal (car file1) (car file2))
169 (not (eval predicate))))))
170 (setq list (cdr list)))
171 list)
172 (setq res (cons file1 res))))
173 (nreverse res))))
174
175(defun dired-files-attributes (dir)
176 "Return a list of all file names and attributes from DIR.
177List has a form of (file-name full-file-name (attribute-list))"
178 (mapcar
179 (lambda (file-name)
180 (let ((full-file-name (expand-file-name file-name dir)))
181 (list file-name
182 full-file-name
183 (file-attributes full-file-name))))
184 (directory-files dir)))
185
91(defun dired-do-chxxx (attribute-name program op-symbol arg) 186(defun dired-do-chxxx (attribute-name program op-symbol arg)
92 ;; Change file attributes (mode, group, owner) of marked files and 187 ;; Change file attributes (mode, group, owner) of marked files and
93 ;; refresh their file lines. 188 ;; refresh their file lines.
@@ -2015,6 +2110,11 @@ If you exit (\\[keyboard-quit], RET or q), you can resume the query replace
2015with the command \\[tags-loop-continue]." 2110with the command \\[tags-loop-continue]."
2016 (interactive 2111 (interactive
2017 "sQuery replace in marked files (regexp): \nsQuery replace %s by: \nP") 2112 "sQuery replace in marked files (regexp): \nsQuery replace %s by: \nP")
2113 (dolist (file (dired-get-marked-files nil nil 'dired-nondirectory-p))
2114 (let ((buffer (get-file-buffer file)))
2115 (if (and buffer (with-current-buffer buffer
2116 buffer-read-only))
2117 (error "File `%s' is visited read-only"))))
2018 (tags-query-replace from to delimited 2118 (tags-query-replace from to delimited
2019 '(dired-get-marked-files nil nil 'dired-nondirectory-p))) 2119 '(dired-get-marked-files nil nil 'dired-nondirectory-p)))
2020 2120