10

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

  • 1
    If this question is as simple as it looks, all you need isdirectory-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 2: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 4:45
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.

  • 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 5:35
  • your solution seems to retrieve only files, but no directory. Please update it when possible. – Tu Do Oct 29 '14 at 7: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 9: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))
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. ;-))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.