如果你f.el使用方便的文件和目录操作库,你只需要函数f-entries。
但是,如果您出于某种原因不想使用此库,并且可以使用非便携式 *nix 解决方案,则可以使用lscommand。
(defun my-directory-files (d)
  (let* ((path (file-name-as-directory (expand-file-name d)))
         (command (concat "ls -A1d " path "*")))
    (split-string (shell-command-to-string command) "\n" t)))
上面的代码就足够了,但为了解释,请进一步阅读。
摆脱点
根据man ls:
   -A, --almost-all
          do not list implied . and ..
通过split-string空格分割字符串,我们可以解析ls输出:
(split-string (shell-command-to-string "ls -A"))
文件名中的空格
问题是某些文件名可能包含空格。split-string默认情况下,由变量中的正则表达式拆分split-string-default-separators,即"[ \f\t\n\r\v]+".
   -1     list one file per line
-1允许用换行符分隔文件,"\n"作为唯一的分隔符传递。您可以将其包装在一个函数中并将其与任意目录一起使用。
(split-string (shell-command-to-string "ls -A1") "\n")
递归
但是,如果您想递归地深入子目录,返回文件以供将来使用,该怎么办?如果您只是更改目录和问题ls,您将获得没有路径的文件名,因此 Emacs 不会知道这些文件的位置。一种解决方案是ls始终返回绝对路径。根据man ls:
   -d, --directory
          list directory entries instead of contents, and do not dereference symbolic links
如果您使用通配符和-d选项将绝对路径传递给目录,那么您将获得立即文件和子目录的绝对路径列表,根据如何在 linux 中列出文件及其绝对路径?. 有关路径构造的说明,请参见在 Elisp 中,如何正确插入斜线的路径字符串?.
(let ((path (file-name-as-directory (expand-file-name d))))
  (split-srting (shell-command-to-string (concat "ls -A1d " path "*")) "\n"))
省略空字符串
Unix 命令必须在输出中添加尾随空格,以便提示位于新行上。否则,而不是:
user@host$ ls
somefile.txt
user@host$
那里将会是:
user@host$ ls
somefile.txtuser@host$
当您将自定义分隔符传递给 时split-string,它会将这个换行符单独视为一行。通常,这允许正确解析 CSV 文件,其中空行可能是有效数据。但是ls我们最终得到一个空字符串,应该通过将t其作为第三个参数传递给split-string.