11

I have a list of file names (with full path) and I want to create a Dired buffer listing this set of files. How would I go about doing that?

How do I create a Dired buffer from a list of file names?

Without using external dependencies.

Malabarba
  • 22,878
  • 6
  • 78
  • 163
Tu Do
  • 6,772
  • 20
  • 39
  • Please clarify. Are the strings in your list a) the names of the files you wish to create, or b) the content of the file (the thing for which you have an absolute path)? – Dan Oct 24 '14 at 19:05
  • @Dan A list of filenames with absolute paths. Just the filenames. – Tu Do Oct 24 '14 at 19:08
  • Actually, it's hard to understand what you're trying to do. Could you explain more? Do these files already exist, or are you really trying to populate a directory with empty files and open up a dired buffer in that directory? – Dan Oct 24 '14 at 19:14
  • @Dan You can assume that the files exist. Let's make it simpler: How do I convert a filename string (with path) into an entry in Dired buffer programmatically? – Tu Do Oct 24 '14 at 19:38
  • 1
    If I understand you correctly, you can just use `(find-file your-directory-path)` to get the relevant `dired` buffer (e.g., `(find-file "/tmp/")` will open up your `tmp` directory in a `dired` buffer). – Dan Oct 24 '14 at 19:42
  • @Dan No, I want to create a Dired buffer from an arbitrary set of files. For example, Dired+ has a feature that can create a union between Dired buffers. But I just want to have a hint how to do something like that but simpler, hence this question, and continue my way. – Tu Do Oct 24 '14 at 20:20
  • 1
    I've edited your question based on what you said in these comments. Feel free to rollback if I got it wrong. – Malabarba Oct 24 '14 at 21:41
  • 3
    If you want to ask about file objects in elisp that's an entirely different question, with a very short answer: there aren't any. :-) – Malabarba Oct 24 '14 at 21:43

2 Answers2

21

C-h f dired tells you the answer. Just pass to dired, as the DIRNAME argument, a list that has as its car the Dired buffer name you want (any string) and as cdr the list of file names you want listed in the buffer. Generally, you want to use absolute file names. For example:

(dired (list "My Dired Buffer Name*"     ; The Dired buffer name
             "/usr/foo/file1.el"         ; First file
             "/usr/bar/toto/some-file.c" ; Second file
             "/whatever/directory/"      ; Third is a directory
             "/a/file/somewhere.zzz"))   ; Fourth

Depending on your platform, names of any nonexistent files and directories you enter might be ignored (not listed), or might raise an error. The former happens if you use ls-lisp.el (e.g. MS Windows). You can force the use of ls-lisp on any platform, if you like (but ls-lisp has fewer ls options), by doing this:

(setq ls-lisp-use-insert-directory-program nil)
(require 'ls-lisp)

If you use library Dired+ (dired+.el) then you can interactively choose files and directories to list: just give dired a non-positive prefix argument (i.e., <= 0). You are then prompted repeatedly for the directories and file names you want listed. You can use file-name wildcards (i.e., * for globbing), to include the matching files and directories. Use C-g to end inputting.

In other words, instead of listing a single directory, the Dired buffer can list any number of directories and file names, which can even belong to different directory trees.

(A non-negative prefix arg (i.e., >= 0) prompts you for the ls listing switches. So a zero prefix arg prompts you for both switches and files/dirs to list: first the ls switches and then the files/dirs.)

Drew
  • 75,699
  • 9
  • 109
  • 225
  • Well I want to do it in Elisp, not using command. I just want a simple code snippet that turn a file name (with full path) into an entry in Dired buffer, similar to how I use `(insert ...)` to insert text into a buffer. – Tu Do Oct 25 '14 at 05:38
  • 1
    @tudo: `dired` is an elisp function. Just evaluate this: `(dired '("my-list" "/home/rekado/dev/script.scm" "/home/rekado/another-file"))` and you get a dired buffer containing these files as @Drew wrote. –  Oct 25 '14 at 06:47
  • @rekado .Thanks. Now I reread the answer correctly it's like what you said. I just want to see an Elisp code snippet like yours, and I thought that Drew gave me a user command answer when I glimpsed it. – Tu Do Oct 25 '14 at 07:05
  • @Drew Please add rekado's example. Thanks for your answer. – Tu Do Oct 25 '14 at 07:10
  • Initially I didn't think it would be this simple, when I see [filesets](http://www.emacswiki.org/FileSets). I thought we must make Dired recognize proper file objects for it to work properly. – Tu Do Oct 25 '14 at 07:21
  • @Drew I'm not sure if this is the behavior of Emacs 24.4, but it signals an error when file does not exist. – Tu Do Oct 25 '14 at 18:14
  • @TuDo: You're right. I've edited that. It does not raise an error - it just prints a message (warning). The command continues normally, with that file or dir name ignored. – Drew Oct 25 '14 at 18:44
  • @Drew it gave a file error: `(file-error "Reading directory" "no such file or directory" "/usr/foo/file1.el")`. – Tu Do Oct 25 '14 at 19:11
  • @TuDo: Perhaps it depends on your platform. On MS Windows, Emacs uses `ls-lisp.el`, and `ls-lisp-insert-directory` for a non-existent file just calls `(message "%s: doesn't exist or is inaccessible" file)` and then `(ding)`. What code is raising that `file-error` for you? – Drew Oct 25 '14 at 19:27
  • @Drew I see. I am using Linux's `ls`, so it signaled an error. – Tu Do Oct 25 '14 at 19:27
  • @TuDo: Try to find out what code is handling the error - e.g., `insert-directory`. You can perhaps tweak the handling of `file-error` so it becomes a no-op. Sounds like this might be good to report as an Emacs bug: there is really no reason (in this context) for the command to fail (IMHO). I'll take a look at vanilla `insert-directory`... – Drew Oct 25 '14 at 19:30
  • @TuDo: Seems to be an unhandled error here, in `insert-directory`: `(access-file file "Reading directory")` (and even if that succeeds, it is followed by a call to `error`). You could try wrapping such stuff in `ignore-errors`, but it probably wouldn't be worth it... – Drew Oct 25 '14 at 19:42
  • @TuDo: FWIW, I filed an Emacs enhancement request for this (#18836). I doubt that anything will come of it, unless they do decide to let Emacs handle `ls` internally (`ls-lisp.el`), which has been discussed. You can force use of `ls-lisp`, if you want: `(setq ls-lisp-use-insert-directory-program nil) (require 'ls-lisp)` – Drew Oct 25 '14 at 20:02
3

Here's a command to do this when the list of files is in a buffer, with one file per line.

(defun dired-virtual-vanilla ()
  (interactive)
  (dired (cons "*Dired*" (split-string (buffer-string) "\n" t))))
killdash9
  • 179
  • 8