comparison lisp/dired-aux.el @ 89909:68c22ea6027c

Sync to HEAD
author Kenichi Handa <handa@m17n.org>
date Fri, 16 Apr 2004 12:51:06 +0000
parents 375f2633d815
children 4c90ffeb71c5
comparison
equal deleted inserted replaced
89908:ee1402f7b568 89909:68c22ea6027c
1 ;;; dired-aux.el --- less commonly used parts of dired -*-byte-compile-dynamic: t;-*- 1 ;;; dired-aux.el --- less commonly used parts of dired -*-byte-compile-dynamic: t;-*-
2 2
3 ;; Copyright (C) 1985, 1986, 1992, 1994, 1998, 2000, 2001 3 ;; Copyright (C) 1985, 1986, 1992, 1994, 1998, 2000, 2001, 2004
4 ;; Free Software Foundation, Inc. 4 ;; Free Software Foundation, Inc.
5 5
6 ;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>. 6 ;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>.
7 ;; Maintainer: FSF 7 ;; Maintainer: FSF
8 ;; Keywords: files 8 ;; Keywords: files
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 Mark files with different names if PREDICATE is nil (or interactively
97 when the user enters empty input at the predicate prompt).
98
99 PREDICATE is a Lisp expression that can refer to the following variables:
100
101 size1, size2 - file size in bytes
102 mtime1, mtime2 - last modification time in seconds, as a float
103 fa1, fa2 - list of file attributes
104 returned by function `file-attributes'
105
106 where 1 refers to attribute of file in the current dired buffer
107 and 2 to attribute of file in second dired buffer.
108
109 Examples of PREDICATE:
110
111 (> mtime1 mtime2) - mark newer files
112 (not (= size1 size2)) - mark files with different sizes
113 (not (string= (nth 8 fa1) (nth 8 fa2))) - mark files with different modes
114 (not (and (= (nth 2 fa1) (nth 2 fa2)) - mark files with different UID
115 (= (nth 3 fa1) (nth 3 fa2)))) and GID."
116 (interactive
117 (list (read-file-name (format "Compare %s with: "
118 (dired-current-directory))
119 (dired-dwim-target-directory))
120 (read-from-minibuffer "Mark if (lisp expr or RET): " nil nil t nil "nil")))
121 (let* ((dir1 (dired-current-directory))
122 (file-alist1 (dired-files-attributes dir1))
123 (file-alist2 (dired-files-attributes dir2))
124 (file-list1 (mapcar
125 'cadr
126 (dired-file-set-difference
127 file-alist1 file-alist2
128 predicate)))
129 (file-list2 (mapcar
130 'cadr
131 (dired-file-set-difference
132 file-alist2 file-alist1
133 predicate))))
134 (dired-fun-in-all-buffers
135 dir1 nil
136 (lambda ()
137 (dired-mark-if
138 (member (dired-get-filename nil t) file-list1) nil)))
139 (dired-fun-in-all-buffers
140 dir2 nil
141 (lambda ()
142 (dired-mark-if
143 (member (dired-get-filename nil t) file-list2) nil)))
144 (message "Marked in dir1: %s files, in dir2: %s files"
145 (length file-list1)
146 (length file-list2))))
147
148 (defun dired-file-set-difference (list1 list2 predicate)
149 "Combine LIST1 and LIST2 using a set-difference operation.
150 The result list contains all file items that appear in LIST1 but not LIST2.
151 This is a non-destructive function; it makes a copy of the data if necessary
152 to avoid corrupting the original LIST1 and LIST2.
153 PREDICATE (see `dired-compare-directories') is an additional match
154 condition. Two file items are considered to match if they are equal
155 *and* PREDICATE evaluates to t."
156 (if (or (null list1) (null list2))
157 list1
158 (let (res)
159 (dolist (file1 list1)
160 (unless (let ((list list2))
161 (while (and list
162 (not (let* ((file2 (car list))
163 (fa1 (caddr file1))
164 (fa2 (caddr file2))
165 (size1 (nth 7 fa1))
166 (size2 (nth 7 fa2))
167 (mtime1 (float-time (nth 5 fa1)))
168 (mtime2 (float-time (nth 5 fa2))))
169 (and
170 (equal (car file1) (car file2))
171 (not (eval predicate))))))
172 (setq list (cdr list)))
173 list)
174 (setq res (cons file1 res))))
175 (nreverse res))))
176
177 (defun dired-files-attributes (dir)
178 "Return a list of all file names and attributes from DIR.
179 List has a form of (file-name full-file-name (attribute-list))"
180 (mapcar
181 (lambda (file-name)
182 (let ((full-file-name (expand-file-name file-name dir)))
183 (list file-name
184 full-file-name
185 (file-attributes full-file-name))))
186 (directory-files dir)))
187
91 (defun dired-do-chxxx (attribute-name program op-symbol arg) 188 (defun dired-do-chxxx (attribute-name program op-symbol arg)
92 ;; Change file attributes (mode, group, owner) of marked files and 189 ;; Change file attributes (mode, group, owner, timestamp) of marked files and
93 ;; refresh their file lines. 190 ;; refresh their file lines.
94 ;; ATTRIBUTE-NAME is a string describing the attribute to the user. 191 ;; ATTRIBUTE-NAME is a string describing the attribute to the user.
95 ;; PROGRAM is the program used to change the attribute. 192 ;; PROGRAM is the program used to change the attribute.
96 ;; OP-SYMBOL is the type of operation (for use in dired-mark-pop-up). 193 ;; OP-SYMBOL is the type of operation (for use in dired-mark-pop-up).
97 ;; ARG describes which files to use, as in dired-get-marked-files. 194 ;; ARG describes which files to use, as in dired-get-marked-files.
104 failures) 201 failures)
105 (setq failures 202 (setq failures
106 (dired-bunch-files 10000 203 (dired-bunch-files 10000
107 (function dired-check-process) 204 (function dired-check-process)
108 (append 205 (append
109 (list operation program new-attribute) 206 (list operation program)
207 (if (eq op-symbol 'touch)
208 '("-t") nil)
209 (list new-attribute)
110 (if (string-match "gnu" system-configuration) 210 (if (string-match "gnu" system-configuration)
111 '("--") nil)) 211 '("--") nil))
112 files)) 212 files))
113 (dired-do-redisplay arg);; moves point if ARG is an integer 213 (dired-do-redisplay arg);; moves point if ARG is an integer
114 (if failures 214 (if failures
136 "Change the owner of the marked (or next ARG) files." 236 "Change the owner of the marked (or next ARG) files."
137 (interactive "P") 237 (interactive "P")
138 (if (memq system-type '(ms-dos windows-nt)) 238 (if (memq system-type '(ms-dos windows-nt))
139 (error "chown not supported on this system")) 239 (error "chown not supported on this system"))
140 (dired-do-chxxx "Owner" dired-chown-program 'chown arg)) 240 (dired-do-chxxx "Owner" dired-chown-program 'chown arg))
241
242 (defun dired-do-touch (&optional arg)
243 "Change the timestamp of the marked (or next ARG) files.
244 This calls touch."
245 (interactive "P")
246 (dired-do-chxxx "Timestamp" dired-touch-program 'touch arg))
141 247
142 ;; Process all the files in FILES in batches of a convenient size, 248 ;; Process all the files in FILES in batches of a convenient size,
143 ;; by means of (FUNCALL FUNCTION ARGS... SOME-FILES...). 249 ;; by means of (FUNCALL FUNCTION ARGS... SOME-FILES...).
144 ;; Batches are chosen to need less than MAX chars for the file names, 250 ;; Batches are chosen to need less than MAX chars for the file names,
145 ;; allowing 3 extra characters of separator per file name. 251 ;; allowing 3 extra characters of separator per file name.
464 ;; Get a clean buffer for error output: 570 ;; Get a clean buffer for error output:
465 (setq err-buffer (get-buffer-create " *dired-check-process output*")) 571 (setq err-buffer (get-buffer-create " *dired-check-process output*"))
466 (set-buffer err-buffer) 572 (set-buffer err-buffer)
467 (erase-buffer) 573 (erase-buffer)
468 (setq default-directory dir ; caller's default-directory 574 (setq default-directory dir ; caller's default-directory
469 err (/= 0 575 err (not (eq 0
470 (apply (function dired-call-process) program nil arguments))) 576 (apply (function dired-call-process) program nil arguments))))
471 (if err 577 (if err
472 (progn 578 (progn
473 (dired-log (concat program " " (prin1-to-string arguments) "\n")) 579 (dired-log (concat program " " (prin1-to-string arguments) "\n"))
474 (dired-log err-buffer) 580 (dired-log err-buffer)
475 (or arguments program t)) 581 (or arguments program t))
562 ("\\.tgz\\'" ".tar" "gunzip") 668 ("\\.tgz\\'" ".tar" "gunzip")
563 ("\\.Z\\'" "" "uncompress") 669 ("\\.Z\\'" "" "uncompress")
564 ;; For .z, try gunzip. It might be an old gzip file, 670 ;; For .z, try gunzip. It might be an old gzip file,
565 ;; or it might be from compact? pack? (which?) but gunzip handles both. 671 ;; or it might be from compact? pack? (which?) but gunzip handles both.
566 ("\\.z\\'" "" "gunzip") 672 ("\\.z\\'" "" "gunzip")
673 ("\\.dz\\'" "" "dictunzip")
674 ("\\.tbz\\'" ".tar" "bunzip2")
567 ("\\.bz2\\'" "" "bunzip2") 675 ("\\.bz2\\'" "" "bunzip2")
568 ;; This item controls naming for compression. 676 ;; This item controls naming for compression.
569 ("\\.tar\\'" ".tgz" nil)) 677 ("\\.tar\\'" ".tgz" nil))
570 "Control changes in file name suffixes for compression and uncompression. 678 "Control changes in file name suffixes for compression and uncompression.
571 Each element specifies one transformation rule, and has the form: 679 Each element specifies one transformation rule, and has the form:
2013 Third arg DELIMITED (prefix arg) means replace only word-delimited matches. 2121 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 2122 If you exit (\\[keyboard-quit], RET or q), you can resume the query replace
2015 with the command \\[tags-loop-continue]." 2123 with the command \\[tags-loop-continue]."
2016 (interactive 2124 (interactive
2017 "sQuery replace in marked files (regexp): \nsQuery replace %s by: \nP") 2125 "sQuery replace in marked files (regexp): \nsQuery replace %s by: \nP")
2126 (dolist (file (dired-get-marked-files nil nil 'dired-nondirectory-p))
2127 (let ((buffer (get-file-buffer file)))
2128 (if (and buffer (with-current-buffer buffer
2129 buffer-read-only))
2130 (error "File `%s' is visited read-only" file))))
2018 (tags-query-replace from to delimited 2131 (tags-query-replace from to delimited
2019 '(dired-get-marked-files nil nil 'dired-nondirectory-p))) 2132 '(dired-get-marked-files nil nil 'dired-nondirectory-p)))
2020 2133
2021 (defun dired-nondirectory-p (file) 2134 (defun dired-nondirectory-p (file)
2022 (not (file-directory-p file))) 2135 (not (file-directory-p file)))
2035 (backward-delete-char 1)) 2148 (backward-delete-char 1))
2036 (message "%s" (buffer-string)))) 2149 (message "%s" (buffer-string))))
2037 2150
2038 (provide 'dired-aux) 2151 (provide 'dired-aux)
2039 2152
2153 ;;; arch-tag: 4b508de9-a153-423d-8d3f-a1bbd86f4f60
2040 ;;; dired-aux.el ends here 2154 ;;; dired-aux.el ends here