Search code examples
emacsdired

Sort files in dired by full path


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

Solution

  • 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))