10

As the title suggests, how do I get all the file entries in a Dired buffer using Elisp?

Tu Do
  • 6,772
  • 20
  • 39
  • 1
    If this question is as simple as it looks, all you need is`directory-files`. – Jordon Biondo Oct 26 '14 at 23:43
  • @JordonBiondo Good to know another more generic function. Originally I intended to use `with-current-buffer` on a Dired buffer to get a list of files or marked files. For a list of all files, I can now use `directory-files`. – Tu Do Oct 27 '14 at 02:50
  • @JordonBiondo I've tried it again. Your method only works when we have "proper" Dired buffer. If we have custom Dired buffer that inserted with arbitrary files from different directories, then `directory-files` is not an option. – Tu Do Oct 27 '14 at 04:45

3 Answers3

7

Manipulating marks seems unnecessary, and perhaps problematic.

Obviously there is functionality within dired to do this sort of thing (albeit not well documented). Here's a simple approach:

;; Silence compile-time warning:
(declare-function dired-map-dired-file-lines "dired-aux")

(defun my-dired-files ()
  "Return a list of files (only) in the current dired buffer."
  (eval-when-compile (require 'cl-lib))
  (require 'dired-aux)
  (let (flist)
    (cl-flet ((fpush (fname) (push fname flist)))
      (dired-map-dired-file-lines #'fpush))
    (nreverse flist)))

Edit:

In the comments you say you'd like the resulting list to include the directory paths as well as the file paths.

dired-map-dired-file-lines explicitly excludes directories, and there's no option to include them; but it's easy to define a function which does, simply by copying the original and omitting the unwanted test:

(defun my-dired-map-over-files-and-dirs (fun)
  "Perform FUN with point at the end of each file or directory line.
FUN takes one argument, the absolute filename."
  (save-excursion
    (let (file buffer-read-only)
      (goto-char (point-min))
      (while (not (eobp))
        (save-excursion
          (and (not (eolp))
               (setq file (dired-get-filename nil t)) ; nil on non-file
               (progn (end-of-line)
                      (funcall fun file))))
        (forward-line 1)))))

Just use this in place of dired-map-dired-file-lines in the initial function. You can then also exclude the declare-function call as well.

You could, of course, further modify this new function to build the desired list directly, instead of calling a function to do that. I feel the more general approach is fine in practice, but you might prefer the idea of wrapping it all into a single function.

phils
  • 48,657
  • 3
  • 76
  • 115
  • Is there non-CL version? I like CL, but I am not able to use CL dependency in Projectile. – Tu Do Oct 27 '14 at 13:50
  • `cl-flet` just defines a function. It makes the code cleaner, but it's still just a function, so define one however you need to. Or don't use `dired-map-dired-file-lines` at all, and instead duplicate and modify its code as needed. – phils Oct 27 '14 at 14:07
  • you are right. Toggling marks clears the old marks, which is problematic. I consider your answer the correct one. – Tu Do Oct 29 '14 at 05:35
  • your solution seems to retrieve only files, but no directory. Please update it when possible. – Tu Do Oct 29 '14 at 07:23
  • Yeah, I've just modified to `dired-get-filename` part to `(dired-get-filename t t)` to get everything. – Tu Do Oct 29 '14 at 09:35
6

I don't know if there's a single function that does this, but this can work for you:

(let (r)
  (dired-unmark-all-files ?\r nil)
  (dired-toggle-marks)
  (setq r (dired-get-marked-files))
  (dired-toggle-marks)
  r)

Sometimes you can simplify it to:

(progn (dired-toggle-marks)
       (dired-get-marked-files))
abo-abo
  • 13,943
  • 1
  • 29
  • 43
3

In addition to @abo-abo's answer, which tells you how to get a list of the file (& dir) names:

Depending on what you want, you can alternatively use dired-copy-filename-as-kill (bound to w) instead of dired-get-marked-files.

It puts the file names into a single, space-separated string, and pushes that string to the kill-ring.

(Space separation means, of course, that it is not so helpful when some of the file names themselves contain space characters. ;-))

Drew
  • 75,699
  • 9
  • 109
  • 225