Question

I am using find-name-dired to find multiple instances of files that all have the same name (call it foo.txt) but in different directories. I want the files listed by alphabetical order of file path. However, they're listed in what looks like a random order. Neither dired-sort-menu nor dired-sort-chiesa will sort the output of find-name-dired, even though it will work on other dired buffers (whose format looks very similar). If I write the contents of the dired buffer to a file, I'm able to open a shell and submit the file to a sort command in the shell that uses the 9th field (the path) as a key. This produces output that looks right, but of course it's no longer a dired buffer.

Is there a way that I can

  1. read in that externally sorted file and open it in dired "mode" (analogous to compilation mode),
  2. sort the output of find-name-dired while still in dired mode, or
  3. produce output from find-name-dired that's sorted the way I want from the beginning?

UPDATE:

Just to make things a bit more concrete, here's the current buffer:

/home/afrankel/Documents/emacs_test/:
find . \( -iname foo.txt \) -exec ls -ld \{\} \;
-rw-r--r--   1 afrankel users        4 Nov 30 16:59 a/foo.txt
-rw-r--r--   1 afrankel users        4 Nov 30 16:59 b/foo.txt
-rw-r--r--   1 afrankel users        4 Nov 30 16:59 d/foo.txt
-rw-r--r--   1 afrankel users        4 Nov 30 16:59 c/z/foo.txt
-rw-r--r--   1 afrankel users        4 Nov 30 16:59 c/foo.txt
-rw-r--r--   1 afrankel users        4 Nov 30 16:59 f/foo.txt
-rw-r--r--   1 afrankel users        4 Nov 30 16:59 e/foo.txt

find finished at Fri Nov 30 17:00:41

Pressing "s" (which would sort most dired buffers) gives the error "Cannot sort this dired buffer".

I want the buffer to look like this:

/home/afrankel/Documents/emacs_test/:
find . \( -iname foo.txt \) -exec ls -ld \{\} \;
-rw-r--r--   1 afrankel users        4 Nov 30 16:59 a/foo.txt
-rw-r--r--   1 afrankel users        4 Nov 30 16:59 b/foo.txt
-rw-r--r--   1 afrankel users        4 Nov 30 16:59 c/foo.txt
-rw-r--r--   1 afrankel users        4 Nov 30 16:59 c/z/foo.txt
-rw-r--r--   1 afrankel users        4 Nov 30 16:59 d/foo.txt
-rw-r--r--   1 afrankel users        4 Nov 30 16:59 e/foo.txt
-rw-r--r--   1 afrankel users        4 Nov 30 16:59 f/foo.txt

find finished at Fri Nov 30 17:00:41
Was it helpful?

Solution 2

Okay, I figured out how to do it using defadvice to automatically change the value of find-ls-option while I'm executing my new wrapper function (find-name-dired-sorted) and then to change it back to its original value.

(defadvice find-name-dired (around find-name-dired-around)
  "Advice: Sort output by path name."
  (let ((find-ls-option (list "-exec ls -ld {} \\; |sort --key=9")))
   ad-do-it))

(defun find-name-dired-sorted (dir pattern)
    "Sort the output of find-name-dired by path name."
    (interactive
     "DFind-name (directory): \nsFind-name (filename wildcard): ")
    (ad-activate 'find-name-dired)
    (find-name-dired dir pattern)
    (ad-deactivate 'find-name-dired))

OTHER TIPS

When you type s in a "normal" Dired buffer, Dired doesn't actually sort the buffer. What it does is to change the value of dired-actual-switches so that it does (or doesn't) contain the -t option ("sort by modification time") and then call revert-buffer which re-runs ls with the new options. This obviously doesn't work in a Dired buffer produced by running find.

What you need to do instead is to arrange to run find with the -s option:

 -s      Cause find to traverse the file hierarchies in lexicographical
         order, i.e., alphabetical order within each directory.

which you can do (for all find-dired commands) by evaluating

(setq find-program "find -s")

Here's one way to do it manually via a temporary change to the configuration:

  1. Run M-x customize-group find-dired.
  2. Change the contents of the field "Find Ls Option" . It should initially read "-exec ls -ld {} \;". Append text to make it read "-exec ls -ld {} \; |sort --key=9". (In other words, sort by field 9, which is the full path treated as a single string.)
  3. Set the option for the current session only.

UPDATE: It's better to do use defadvice, as I did in my other (later) answer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top