If you set -F or --classify in the dired-actual-switches then it places a / at the end of directory names and * at the end of executables. When you finish renaming the files, these characters are taken literally so every directory it will try to move it inside of itself if it was renamed.

Of note, I have recently switched to emacs 27 head, so I can't remember if this happened in Emacs 26.1 or not when switching.

I tried to use this hacky solution to remove --classify from dired-actual-switches but it doesn't seem to work. Is there a better to do this? Maybe wrapping an advice around wdired instead of using the hooks might be better but not sure how to do that.

(defvar-local jj/dired-classify-enabled nil)

(add-hook 'wdired-mode-hook
      (lambda ()
        (if (string-match "--classify " dired-actual-switches)
        (setq jj/dired-classify-enabled t))
        (setq dired-actual-switches
          (if (string-match "--classify " dired-actual-switches)
              (replace-match "" t t dired-actual-switches)))))

(add-hook 'dired-mode-hook
      (lambda ()
        (cond ((eq jj/dired-classify-enabled t)
           (setq jj/dired-classify-enabled nil)
           (setq dired-actual-switches
             (if (string-match "-a " dired-actual-switches)
                 (replace-match "-a --classify" t t dired-actual-switches)))))))

Edit: I noticed the above works to remove the --classify when entering wdired-mode but I have to call revert-buffer to get it to update properly. I tried putting revert-buffer in the wdired-mode-hook but then I got errors.

Edit2:I've figured out how to do this with defadvice. I'd greatly appreciate someones help with using emacs regex functions and syntax. If someone can modify my answer below for a version using regex instead of just removing --classify and readding it that would be great and I will accept your answer.

Edit2: Root on my mac seems to not recognize --classify but only -F, so if using root for dired best to change the script to use -F instead of --classify. This could be due to an old version of gnutils ls on the system that is possibly fixed in newer versions.

  • If you see this even when you start Emacs using emacs -Q then please consider filing a bug report / enhancement request, using M-x report-emacs-bug. – Drew Feb 21 '19 at 15:30
  • @Drew Done. I figured out how to write an advice around wdired-change-mode to remove and add the classify back to the switches. It was a quick hack so maybe see if someone has a better idea here but currently at least it is working. – J Spen Feb 22 '19 at 5:38
  • If you feel you have an answer that might help someone else then please consider adding it as an answer. You can accept your own answer, BTW. – Drew Feb 22 '19 at 6:05
  • @Drew okay I'll add it but it is a hacky one for my setup. Really should use regex to check for matching and remove any relevant switches. Save the current switches to set after. – J Spen Feb 22 '19 at 10:33
  • @Drew I posted for now. I was hoping someone will help with the regex to make this work universally across anyone's setup. Maybe I will need a different post with strictly regex help to get the answer. – J Spen Feb 22 '19 at 10:41

Here is my solution that works for my setup but won't work universally. Need to change this to using regex and removing any -F or --classify switches. Then, saving the current state of the switches to set back to when wdired changes back to dired. If anyone has any ideas how to implement this using regex in emacs, would be greatly appreciated. I don't know emacs regex string functions or syntax well.

(defun jj/dired-sort-toggle-reverse-switch ()
  "Toggle ls -r switch and update buffer.
Does not affect other sort switches."
  (let (case-fold-search)
    (setq dired-actual-switches
      (if (string-match "-r " dired-actual-switches)
          (replace-match "" t t dired-actual-switches)
        (concat "-r " dired-actual-switches)))

(defun jj/dired-sort-remove-classify-switch ()
  "Remove --classify switch.
TODO: Change to using regex to remove any -F or --classify switches."
  (let (case-fold-search)
    (setq dired-actual-switches
      (if (string-match "--classify " dired-actual-switches)
          (replace-match "" t t dired-actual-switches)
        (concat dired-actual-switches)))
    ;; Don't need as doesn't change the mode-line currently
    ;; (dired-sort-set-mode-line)

(defun jj/dired-sort-add-classify-switch ()
  "Add --classify switch after -a.
TODO: change to using regex"
  (let (case-fold-search)
    (cond ((string-match "--classify " dired-actual-switches))
       (setq dired-actual-switches
         (if (string-match "-a " dired-actual-switches)
             (replace-match "-a --classify " t t dired-actual-switches)
           (concat dired-actual-switches)))

;; Possibly use this to solve the above problem
(defvar-local jj/wdired-classify-enabled nil)
(defun jj/wdired-before-start-advice ()
  "Execute when switching from `dired' to `wdired'."
  ;; TODO: Change to save current dired-switches if the add and remove functions use regex
  (setq jj/wdired-classify-enabled
    (if (string-match "--classify " dired-actual-switches)
        t nil))
  (when (string-match "--classify " dired-actual-switches)
(defun jj/wdired-after-finish-advice ()
  "Execute when switching from `wdired' to `dired'"
  (when (eq jj/wdired-classify-enabled t)
    ;; can save the current switches in defvar-local and set here instead
    (setq jj/wdired-classify-enabled nil)))
(advice-add 'wdired-change-to-wdired-mode :before #'jj/wdired-before-start-advice)
(advice-add 'wdired-change-to-dired-mode :after #'jj/wdired-after-finish-advice)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.