[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/dired-duplicates 5b2a23dd52 01/57: Check in first worki
|
From: |
ELPA Syncer |
|
Subject: |
[elpa] externals/dired-duplicates 5b2a23dd52 01/57: Check in first working version |
|
Date: |
Sat, 4 Nov 2023 06:58:25 -0400 (EDT) |
branch: externals/dired-duplicates
commit 5b2a23dd52749c8c56815faa1e3455fae858aae0
Author: Harald Judt <h.judt@gmx.at>
Commit: Harald Judt <h.judt@gmx.at>
Check in first working version
---
find-dupes-dired.el | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 96 insertions(+)
diff --git a/find-dupes-dired.el b/find-dupes-dired.el
new file mode 100644
index 0000000000..738bb1fb08
--- /dev/null
+++ b/find-dupes-dired.el
@@ -0,0 +1,96 @@
+(defcustom find-dupes-separator-file
+ (concat "/tmp/-" (make-string 40 ?-))
+ "Path and name of the separator file that will be created (and deleted) for
making search results easier to discern."
+ :group 'find-dupes-dired
+ :tag "Dummy separator file. It will be created immediately before and
deleted as soon as possible after the search operation finishes."
+ :type 'string)
+
+(defcustom find-dupes-checksum-exec
+ "sha256sum"
+ "Name of the executable used for creating file checksums for comparison."
+ :group 'find-dupes-dired
+ :tag "Checksum executable"
+ :type 'string)
+
+(defvar find-dupes-directories nil
+ "List of directories that will be searched for duplicate files.")
+
+(defun find-dupes-checksum-file (file)
+ "Create a checksum for `file', using executable defined by
`find-dupes-checksum-exec'."
+ (let* ((default-directory (file-name-directory (expand-file-name file)))
+ (exec (executable-find find-dupes-checksum-exec t)))
+ (unless exec
+ (error "Checksum program %s not found in exec-path!" exec))
+ (first (split-string
+ (shell-command-to-string
+ (concat exec " \"" (expand-file-name (file-local-name file))
"\""))
+ nil
+ t))))
+
+(defun find-dupes--ensure-separator-file ()
+ "Ensure that the separator file specified by `find-dupes-separator-file'
exists."
+ (unless (file-exists-p find-dupes-separator-file)
+ (make-empty-file find-dupes-separator-file)))
+
+(defun find-dupes--remove-separator-file ()
+ "Remove the separator file specified by `find-dupes-separator-file'."
+ (delete-file find-dupes-separator-file nil))
+
+(defun find-dupes--duplicate-files (directories)
+ "Given one or more root directories, search inside below the
+directories for duplicate files. Returns a hash-table with the
+generated checksums as keys and files as values."
+ (cl-loop with files = (mapcan #'(lambda (d) (directory-files-recursively d
".*"))
+ (ensure-list directories))
+ and same-size-table = (make-hash-table)
+ and checksum-table = (make-hash-table :test 'equal)
+ for f in files
+ for size = (file-attribute-size (file-attributes f))
+ do (setf (gethash size same-size-table)
+ (append (gethash size same-size-table) (list f)))
+ finally
+ (cl-loop for size being the hash-key in same-size-table using
(hash-value same-size-files)
+ if (> (length same-size-files) 1) do
+ (cl-loop for f in same-size-files
+ for checksum = (find-dupes-checksum-file f)
+ do (setf (gethash checksum checksum-table)
+ (append (gethash checksum
checksum-table) (list f)))))
+ (cl-loop for checksum being the hash-key in checksum-table using
(hash-value same-files)
+ when (< (length same-files) 2) do
+ (remhash checksum checksum-table))
+ (cl-return checksum-table)))
+
+(defun find-dupes--generate-dired-list (&optional directories)
+ "Generate a list of grouped duplicate files, separated by a
+separator file specified by `find-dupes-separator-file'."
+ (cl-loop with dupes-table = (find-dupes--duplicate-files (or directories
+
find-dupes-directories))
+ for files being the hash-values in dupes-table
+ appending (append files (list find-dupes-separator-file))))
+
+(defun find-dupes-revert-function (&optional arg noconfirm)
+ "Revert function used instead of `dired-revert' for dired buffers generated
by find-dupes."
+ (setq-local dired-directory
+ (append (list (first dired-directory))
+ (find-dupes--generate-dired-list)))
+ (find-dupes--ensure-separator-file)
+ (dired-revert)
+ (find-dupes--remove-separator-file))
+
+(defun find-dupes-dired (directories)
+ "Find a list of duplicate files inside one or more directories
+and show them in a dired buffer."
+ (interactive "f")
+ (let ((default-directory "/"))
+ (find-dupes--ensure-separator-file)
+ (dired (cons "/" (find-dupes--generate-dired-list directories)))
+ (setq-local find-dupes-directories directories)
+ (setq-local revert-buffer-function 'find-dupes-revert-function)
+ (find-dupes--remove-separator-file)))
+
+;;;; Tests
+;; (find-dupes-checksum-file "~/tmp/my-file")
+;; (find-dupes--duplicate-files "~/my-dir")
+;; (find-dupes-dired "~/my-dir")
+
+(provide 'find-dupes-dired)
- [elpa] externals/dired-duplicates b3d03d2f9f 18/57: Rename find-dupes-use-separator-file to find-dupes-use-separators, (continued)
- [elpa] externals/dired-duplicates b3d03d2f9f 18/57: Rename find-dupes-use-separator-file to find-dupes-use-separators, ELPA Syncer, 2023/11/04
- [elpa] externals/dired-duplicates 9f78542fd1 20/57: Add lexical binding declaration, ELPA Syncer, 2023/11/04
- [elpa] externals/dired-duplicates 5b9d946fbb 24/57: Require dired, ELPA Syncer, 2023/11/04
- [elpa] externals/dired-duplicates 4bd4f6ff94 27/57: flymake: Add package name and small description line, ELPA Syncer, 2023/11/04
- [elpa] externals/dired-duplicates 2c9131c639 32/57: Add .gitignore file, ELPA Syncer, 2023/11/04
- [elpa] externals/dired-duplicates d50460da29 34/57: Unquote lambda, ELPA Syncer, 2023/11/04
- [elpa] externals/dired-duplicates 6aa879e46a 35/57: Use temporary-file-directory instead of hard-coded /tmp, ELPA Syncer, 2023/11/04
- [elpa] externals/dired-duplicates 9156ee4483 39/57: Rename find-duplicates.el to dired-duplicates.el, ELPA Syncer, 2023/11/04
- [elpa] externals/dired-duplicates 383fda8403 45/57: Update README.org after latest changes, ELPA Syncer, 2023/11/04
- [elpa] externals/dired-duplicates 8b457f029c 51/57: Remove :group declaration from customizations, ELPA Syncer, 2023/11/04
- [elpa] externals/dired-duplicates 5b2a23dd52 01/57: Check in first working version,
ELPA Syncer <=
- [elpa] externals/dired-duplicates fe6b60acec 37/57: Remove exclamation mark from user-error, ELPA Syncer, 2023/11/04
- [elpa] externals/dired-duplicates 8bd3de781d 55/57: Optimize processing of same-size-files and same-files, ELPA Syncer, 2023/11/04
- [elpa] externals/dired-duplicates 2c6caf10a2 52/57: Shorten :type declaration in sort order defcustom, ELPA Syncer, 2023/11/04
- [elpa] externals/dired-duplicates bff2363b18 02/57: Make find-dupes-dired accept multiple directories as input, ELPA Syncer, 2023/11/04
- [elpa] externals/dired-duplicates 0dc7295626 03/57: Handle case when no duplicate files found, ELPA Syncer, 2023/11/04
- [elpa] externals/dired-duplicates 24b57254eb 05/57: Print message when reverting dired buffer, ELPA Syncer, 2023/11/04
- [elpa] externals/dired-duplicates cab41ca722 08/57: Remove commented test calls, ELPA Syncer, 2023/11/04
- [elpa] externals/dired-duplicates c2cb23cd0c 07/57: Allow sorting by filesize in ascending or descending order, ELPA Syncer, 2023/11/04
- [elpa] externals/dired-duplicates 194d22be42 10/57: Reformat custom value definitions, ELPA Syncer, 2023/11/04
- [elpa] externals/dired-duplicates 0d71465d6a 13/57: Make the use of the dummy separator file optional, ELPA Syncer, 2023/11/04