Obtenga todos los nombres de archivo en el búfer Dired actual con Elisp

10

Como sugiere el título, ¿cómo obtengo todas las entradas de archivo en un búfer Dired usando Elisp?

Tu Do
fuente
1
Si esta pregunta es tan simple como parece, todo lo que necesita es directory-files.
Jordon Biondo
@JordonBiondo Es bueno saber otra función más genérica. Originalmente tenía la intención de usar with-current-bufferun búfer Dired para obtener una lista de archivos o archivos marcados. Para obtener una lista de todos los archivos, ahora puedo usar directory-files.
Tu Do
@JordonBiondo Lo he intentado de nuevo. Su método solo funciona cuando tenemos el búfer Dired "adecuado". Si tenemos un búfer Dired personalizado que se inserta con archivos arbitrarios de diferentes directorios, entonces directory-filesno es una opción.
Tu Do

Respuestas:

7

Manipular las marcas parece innecesario y quizás problemático.

Obviamente, existe una funcionalidad dentro de la dirección para hacer este tipo de cosas (aunque no está bien documentada). Aquí hay un enfoque simple:

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

Editar:

En los comentarios que dice que desea que la lista resultante incluya las rutas del directorio, así como las rutas del archivo.

dired-map-dired-file-linesexcluye explícitamente los directorios, y no hay opción para incluirlos; pero es fácil definir una función que lo haga, simplemente copiando el original y omitiendo la prueba no deseada:

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

Simplemente use esto en lugar de dired-map-dired-file-linesen la función inicial. Entonces también puede excluir la declare-functionllamada.

Por supuesto, podría modificar aún más esta nueva función para crear la lista deseada directamente, en lugar de llamar a una función para hacerlo. Creo que el enfoque más general está bien en la práctica, pero es posible que prefiera la idea de envolverlo todo en una sola función.

phils
fuente
¿Hay una versión que no sea CL? Me gusta CL, pero no puedo usar la dependencia de CL en Projectile.
Tu Do
cl-fletsolo define una función. Hace que el código sea más limpio, pero sigue siendo solo una función, así que defina uno como lo necesite. O no lo use dired-map-dired-file-linesen absoluto, y en su lugar duplique y modifique su código según sea necesario.
phils
tienes razón. Alternar marcas borra las marcas antiguas, lo cual es problemático. Considero que su respuesta es la correcta.
Tu Do
su solución parece recuperar solo archivos, pero ningún directorio. Actualízalo cuando sea posible.
Tu Do
Sí, acabo de modificar a dired-get-filenameparte (dired-get-filename t t)para obtener todo.
Tu Do
6

No sé si hay una sola función que haga esto, pero esto puede funcionar para usted:

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

A veces puedes simplificarlo a:

(progn (dired-toggle-marks)
       (dired-get-marked-files))
abo-abo
fuente
3

Además de la respuesta de @ abo-abo, que le indica cómo obtener una lista de los nombres de archivo (y directorio):

Dependiendo de lo que desee, puede usar alternativamente dired-copy-filename-as-kill(vinculado a w) en lugar de dired-get-marked-files.

Pone los nombres de archivo en una cadena única, separada por espacios , y empuja esa cadena a kill-ring.

(La separación del espacio significa, por supuesto, que no es tan útil cuando algunos de los nombres de archivo contienen caracteres de espacio. ;-))

Dibujó
fuente