As the title suggests, how do I get all the file entries in a Dired buffer using Elisp?
-
1If 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 Answers
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.

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

- 13,943
- 1
- 29
- 43
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. ;-))

- 75,699
- 9
- 109
- 225