aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-23 20:20:17 -0500
committerCraig Jennings <c@cjennings.net>2026-05-23 20:20:17 -0500
commit4a7927bf7352e3e626dfb596a70bec9d3bc532eb (patch)
tree777b100ea74f4c41691773a5e3f375f9090b54c2 /modules
parent1ab0ac6397b1e41ae124d3990ba2dd20bca2cfe3 (diff)
downloaddotemacs-4a7927bf7352e3e626dfb596a70bec9d3bc532eb.tar.gz
dotemacs-4a7927bf7352e3e626dfb596a70bec9d3bc532eb.zip
fix(dwim-shell): make destructive file-op commands match their names
Two commands did less, or more, than their names implied. remove-empty-directories ran find . -type d -empty -delete from whatever the current directory happened to be, so its scope was implicit and easy to misjudge. It now prompts for a root, names that root in the confirmation, and runs find against the shell-quoted root via cj/dwim-shell--empty-dirs-command. secure-delete ran shred without -u, so it overwrote a file's contents but left the file in place, not the deletion the name and the "permanently destroy" prompt promise. Added -u so it unlinks after overwriting.
Diffstat (limited to 'modules')
-rw-r--r--modules/dwim-shell-config.el32
1 files changed, 23 insertions, 9 deletions
diff --git a/modules/dwim-shell-config.el b/modules/dwim-shell-config.el
index a68f0a22..093ffa77 100644
--- a/modules/dwim-shell-config.el
+++ b/modules/dwim-shell-config.el
@@ -169,6 +169,13 @@ single-quoted destination it is interpolated into."
(and (stringp prefix)
(string-match-p "\\`[[:alnum:] ._-]*\\'" prefix)))
+(defun cj/dwim-shell--empty-dirs-command (root)
+ "Return a find command that deletes empty directories under ROOT.
+ROOT is shell-quoted so paths with spaces survive, and a trailing inert
+=<<*>>= comment makes dwim-shell run the command once rather than once per
+marked file."
+ (format "find %s -type d -empty -delete # <<*>>" (shell-quote-argument root)))
+
(defun cj/dwim-shell--build-concat-filelist (files)
"Return ffmpeg concat-demuxer filelist text for FILES.
Each path becomes a single-quoted `file' line with embedded single quotes
@@ -671,13 +678,18 @@ all marked files rather than once per file."
:utils (if (eq system-type 'darwin) "say" "espeak"))))
(defun cj/dwim-shell-commands-remove-empty-directories ()
- "Remove all empty directories recursively."
- (interactive)
- (when (yes-or-no-p "Remove all empty directories? ")
- (dwim-shell-command-on-marked-files
- "Remove empty dirs"
- "find . -type d -empty -delete"
- :utils "find")))
+ "Remove empty directories under a chosen root.
+Prompts for the root (defaulting to the current directory) and names it in the
+confirmation, so the scope is explicit instead of whatever the current
+directory happens to be."
+ (interactive)
+ (let ((root (expand-file-name
+ (read-directory-name "Remove empty dirs under: " default-directory))))
+ (when (yes-or-no-p (format "Remove all empty directories under %s? " root))
+ (dwim-shell-command-on-marked-files
+ "Remove empty dirs"
+ (cj/dwim-shell--empty-dirs-command root)
+ :utils "find"))))
(defun cj/dwim-shell-commands-create-thumbnail-from-image ()
"Create thumbnail(s) from image(s)."
@@ -764,12 +776,14 @@ in the process list."
:utils "chmod"))
(defun cj/dwim-shell-commands-secure-delete ()
- "Securely delete file(s) by overwriting with random data."
+ "Securely delete file(s): overwrite with random data, then remove.
+Uses =shred -u= so the file is unlinked after overwriting, matching the
+\"delete\" the command name and prompt promise."
(interactive)
(when (yes-or-no-p "This will permanently destroy files. Continue? ")
(dwim-shell-command-on-marked-files
"Secure delete"
- "shred -vfz -n 3 '<<f>>'"
+ "shred -vfzu -n 3 '<<f>>'"
:utils "shred")))
(defun cj/dwim-shell-commands-sanitize-filename ()