如果你f.el
使用方便的文件和目录操作库,你只需要函数f-entries
。
但是,如果您出于某种原因不想使用此库,并且可以使用非便携式 *nix 解决方案,则可以使用ls
command。
(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
.