Sort emacs dired buffer according to custom comparator

450 Views Asked by At

It does not seem that dired provides an interface to sort the files/folders according to an arbitrary comparator function. (By default it only allows sorting by name and by date).

I have been digging into the source code in order to determine the mechanism for this sorting, and I see that it is the call to (revert-buffer) in dired-sort-toggle (in dired.el) which does the redisplaying. This leads me to realize that dired simply runs an ls command with certain switches, and then reads the output into the buffer.

Is there a better way to achieve this custom sorting than to point dired's ls function to a custom one? I feel that there could be a variable which holds the ordered list of files/directories in the dired buffer, which I could potentially re-arrange.

I have found the variable dired-subdir-alist, but this only seems to contain the top directory (even though according to the documentation, this seems like exactly the list I want)

dired-subdir-alist is a variable defined in `dired.el'. Documentation: Association list of subdirectories and their buffer positions. Each subdirectory has an element: (DIRNAME . STARTMARKER). The order of elements is the reverse of the order in the buffer. In simple cases, this list contains one element.

How could I find such a variable?

3

There are 3 best solutions below

0
On

Your understanding is correct. And, as @Stefan notes, ls-lisp.el provides some flexibility.

See also library Dired Sort Menu, which at least provides more ls possibilities and lets you combine sort orders. (It does not let you provide an arbitrary sort order, however -- for that, see ls-lisp.el.)

0
On

Old thread, but this is the top hit when searching on this issue.

Instead of mucking around in ls-lisp internals, it was easier to implement a sorting function (e.g., with sort-regexp-fields) and bind it to dired-mode-map. You have to temporarily inhibit read-only mode to do this. E.g., I have a directory with files in format "FIELD1==FIELD2--FIELD3" and I want to sort by FIELD2:

(defun my-sort-field2 ()
  (interactive)
  (setq inhibit-read-only t)
  (sort-regexp-fields nil "^.*$" "==.*--" (point-min) (point-max))
  (setq inhibit-read-only nil))

This will let you do all kinds of arbitrary sorting and manipulation of insert-directory results. For example, you can restrict the sorting above to specific a specific directory by wrapping it in a conditional.

1
On

You might like to use ls-lisp, which is an Elisp implementation of insert-directory, which is the function used by Dired to (normally) run ls. This is used typically under Windows where ls is often absent:

(require 'ls-lisp)

It should be easy to tweak the code to be able to use your own sorting function.