如何在 Common Lisp 中迭代目录?
我在 Darwin 上使用 OpenMCL,我想做一些类似的事情:
(loop for f in (directory "somedir")
collect (some-per-file-processing f))
但是我无法让 directory
返回除 NIL
以外的任何内容,而且我可以'似乎在网上找不到任何好的解释(除了“每个系统的不同”)。
有什么指点吗?
I'm using OpenMCL on Darwin, and I'd like to do something like:
(loop for f in (directory "somedir")
collect (some-per-file-processing f))
But I can't get directory
to return anything other than NIL
, and I can't seem to find any good explanation online (other than "its different for each system").
Any pointers?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
基本上有两种指定路径名的方法:
使用字符串
字符串显然取决于平台:例如 Unix 语法与 Windows 语法。
您可以从字符串创建路径名对象:
上面的
#p
确保在您读回路径名对象(而不是字符串)时创建它。因此,Common Lisp 在内部使用路径名对象,但它允许您使用普通字符串并根据需要从它们创建路径名对象。
当 Common Lisp 发现路径名未指定所有组件(例如缺少目录)时,它会从路径名对象中填充组件,该对象是变量
*DEFAULT-PATHNAME-DEFAULTS* .
使用 DESCRIBE 函数,您可以查看路径名的组成部分(此处为 Clozure CL):
使用 Lisp 函数创建路径名对象
MAKE-PATHNAME
是函数,它需要一些关键字参数来指定组件。有时,基于现有路径名创建新路径名也很有用:
如果使用函数
DIRECTORY
,则使用带通配符的路径名会很有用。DIRECTORY
然后将返回匹配路径名的列表。名称DIRECTORY
有点误导,因为DIRECTORY
不列出目录的内容,而是列出(通常)带有通配符的路径名的匹配路径名。通配符可以匹配/foo/s*c/list*.l*
等组件中的字符序列。还有通配符**
,用于匹配目录层次结构的一部分,例如/foo/**/test.lisp
,它匹配所有文件test.lisp
位于目录foo
及其子目录下。上面应该返回
/Users/foo/Lisp/ 及其所有子目录中的所有
lisp
文件的列表。要返回单个目录中的
.c
文件,请使用:请注意,
DIRECTORY
返回 pathname 对象列表(而不是字符串列表)。上面使用了由
MAKE-PATHNAME
创建的路径名对象。它返回所有匹配/Lisp/cl-http/cl-http-342/server/md5.*
的文件。这与: 相同,
后者更短,但取决于 Unix 路径名语法。
There are basically two ways to specify pathnames:
Using strings
Strings are obviously depending on the platform: Unix syntax vs. Windows syntax for example.
You can create a pathname object from a string:
The
#p
above assures that a pathname object (and not a string) is created, when you read it back.So, internally Common Lisp works with pathname objects, but it lets you use normal strings and makes pathname objects from them if needed.
When Common Lisp sees a pathname that has not all components specified (for example the directory is missing), then it fills in the components from the pathname object that is the value of the variable
*DEFAULT-PATHNAME-DEFAULTS*
.With the function DESCRIBE you can look at the components of a pathname (here Clozure CL):
Using the Lisp functions creating pathname objects
MAKE-PATHNAME
is the function and it takes a few keyword arguments to specify the components.Sometimes it is also useful to create a new pathname based on an existing one:
If you use the function
DIRECTORY
it is useful to use a pathname with wildcards.DIRECTORY
then will return a list of matching pathnames. The nameDIRECTORY
is slightly misleading, sinceDIRECTORY
does not list the contents of a directory, but lists the matching pathnames for (usually) a pathname with wildcards. The wildcards can match a sequences of characters in components like/foo/s*c/list*.l*
. There is also the wild card**
, which is used to match parts of a directory hierarchy like/foo/**/test.lisp
, which matches all filestest.lisp
under the directoryfoo
and its subdirectories.Above should return a list of all
lisp
files in/Users/foo/Lisp/
and all its subdirectories.To return the
.c
files in a single directory use:Note that
DIRECTORY
returns a list of pathname objects (not a list of strings).Above uses a pathname object that is created by
MAKE-PATHNAME
. It returns all the files that match/Lisp/cl-http/cl-http-342/server/md5.*
.This is the same as:
which is shorter, but depends on the Unix pathname syntax.
您的路径名规范是否包含通配符? Common Lisp 的路径名一开始有点难以掌握 - 至少对我来说是......作为 CLHS 在
directory
函数上声明:为了让你的路径名包含通配符,你可以尝试 make-pathname 函数,比如
或者甚至
我发现了 CL-FAD 库对于处理路径名和文件系统有很大帮助。特别是,它的
list-directory
功能可能更容易使用比普通的标准目录
功能。Does your pathname specification contain a wildcard? Common Lisp's pathname stuff is somewhat hard to grasp at first - at least for me it was... As the CLHS states on the
directory
function:In order to have your pathname include a wildcard, you might try the make-pathname function, like
Or even
I found the CL-FAD library a great help for dealing with pathnames and the file system. In particular, its
list-directory
function might be easier to use than the plain standarddirectory
function.实现目录列表的现代 Common Lisp 库是 IOLIB。
它的工作原理如下:
请注意,不需要尾部斜杠或通配符。它非常强大,甚至可以处理带有错误编码的 unicode 字符的文件名。
与 CL-FAD 的区别:
The modern Common Lisp library implementing directory listing is IOLIB.
It works like this:
Note that no trailing slash or wildcards are required. It is very robust and can even process file names with incorrectly encoded unicode characters.
Differences compared to CL-FAD:
为了代码片段,我将添加一个适合我的示例。我使用 osicat (类似于 cl-fad)和 str。
编辑:也可使用
uiop:directory-files
。 str:包含?可以通过搜索
来完成。返回
如果正确使用通配符,它肯定可以得到改进。不过,这是您现在可以使用的代码片段:)
参考资料:
I'll add an example that works for me, for the sake of a code snippet. I use osicat (similar to cl-fad) and str.
edit: also with
uiop:directory-files
. str:contains? could be done withsearch
.returns
It can certainly be improved my a proper use of wildcards. However that's a snippet you can use right now : )
References: