comparison lisp/dired-aux.el @ 53215:99f19d6d7aeb

(dired-do-query-replace-regexp): Report files visited read-only. (dired-compare-directories): New command. (dired-file-set-difference, dired-files-attributes): New functions.
author Richard M. Stallman <rms@gnu.org>
date Mon, 01 Dec 2003 01:56:19 +0000
parents 695cf19ef79e
children 79093b308520
comparison
equal deleted inserted replaced
53214:931e46b73703 53215:99f19d6d7aeb
86 diff-switches 86 diff-switches
87 (mapconcat 'identity diff-switches " ")))) 87 (mapconcat 'identity diff-switches " "))))
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.
93 Compare file attributes of files in the current directory
94 with file attributes in directory DIR2 using PREDICATE on pairs of files
95 with the same name. Mark files for which PREDICATE returns non-nil.
96
97 PREDICATE 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
107 Examples 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.
148 The result list contains all file items that appear in LIST1 but not LIST2.
149 This is a non-destructive function; it makes a copy of the data if necessary
150 to avoid corrupting the original LIST1 and LIST2.
151 PREDICATE (see `dired-compare-directories') is an additional match
152 condition. 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.
177 List 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.
94 ;; ATTRIBUTE-NAME is a string describing the attribute to the user. 189 ;; ATTRIBUTE-NAME is a string describing the attribute to the user.
95 ;; PROGRAM is the program used to change the attribute. 190 ;; PROGRAM is the program used to change the attribute.
2013 Third arg DELIMITED (prefix arg) means replace only word-delimited matches. 2108 Third arg DELIMITED (prefix arg) means replace only word-delimited matches.
2014 If you exit (\\[keyboard-quit], RET or q), you can resume the query replace 2109 If you exit (\\[keyboard-quit], RET or q), you can resume the query replace
2015 with the command \\[tags-loop-continue]." 2110 with 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
2021 (defun dired-nondirectory-p (file) 2121 (defun dired-nondirectory-p (file)
2022 (not (file-directory-p file))) 2122 (not (file-directory-p file)))