如何在Common Lisp中遍历目录?
我在达尔文使用OpenMCL,我想做一些类似的事情:如何在Common Lisp中遍历目录?,lisp,filesystems,directory,common-lisp,Lisp,Filesystems,Directory,Common Lisp,我在达尔文使用OpenMCL,我想做一些类似的事情: (loop for f in (directory "somedir") collect (some-per-file-processing f)) 但是我无法让目录返回除NIL之外的任何内容,而且我似乎也无法在网上找到任何好的解释(除了“每个系统都不同”) 有指针吗?您的路径名规范是否包含通配符?Common Lisp的路径名一开始有点难理解-至少对我来说是。。。与目录功能上的状态相同: 如果pathspec不是wild,则 结果列表
(loop for f in (directory "somedir")
collect (some-per-file-processing f))
但是我无法让目录
返回除NIL
之外的任何内容,而且我似乎也无法在网上找到任何好的解释(除了“每个系统都不同”)
有指针吗?您的路径名规范是否包含通配符?Common Lisp的路径名一开始有点难理解-至少对我来说是。。。与
目录
功能上的状态相同:
如果pathspec不是wild,则
结果列表将包含
零或一个元素
为了让您的路径名包含通配符,您可以尝试使用makepathname函数,如
(directory (make-pathname :directory '(:absolute "srv" "hunchentoot") :name :wild :type "lisp"))
甚至
(directory (make-pathname :directory '(:absolute "srv" "hunchentoot") :name :wild :type :wild))
我发现这个库对处理路径名和文件系统有很大帮助。特别是,它的函数可能比普通标准的
目录
函数更易于使用。指定路径名基本上有两种方法:
- 使用字符串
"/Users/foo/bar.text" is a valid pathname
"/Users/foo/*/foo.*" is a valid pathname with two wildcards
可以从字符串创建路径名对象:
? (pathname "/Users/bar/foo.text")
#P"/Users/bar/foo.text"
上面的#p确保在读回pathname对象时创建了该对象(而不是字符串)
? #P"/Users/bar/foo.text"
#P"/Users/bar/foo.text"
因此,内部公共Lisp可以处理路径名对象,但它允许您使用普通字符串,并在需要时从中生成路径名对象
当Common Lisp看到未指定所有组件的路径名(例如,缺少目录)时,它将填充pathname对象中的组件,该对象是variabel*DEFAULT-pathname-DEFAULTS*的值
使用函数descripe,您可以查看路径名的组件(此处为Clozure CL):
如果使用目录,则使用带有通配符的路径名非常有用。目录将返回匹配路径名的列表。名称“DIRECTORY”有点误导,因为DIRECTORY不列出目录的内容,而是列出(通常)带有通配符的路径名的匹配路径名。通配符可以匹配组件中的字符序列,如/foo/s*c/list*.l*”。还有通配符**,用于匹配目录层次结构的部分,如/foo/**/test.lisp,它匹配目录foo及其子目录下的所有文件test.lisp
(directory "/Users/foo/Lisp/**/*.lisp")
上面应该返回“/Users/foo/lisp/”及其所有子目录中所有“lisp”文件的列表
(directory "/Users/foo/Lisp/**/*.lisp")
要返回单个目录中的.c文件,请使用:
(directory "/Users/foo/c/src/*.c")
请注意,目录返回路径名对象列表(而不是字符串列表)
上面使用MAKE-pathname创建的路径名对象。它返回与/Lisp/cl-http/cl-http-342/server/md5.*匹配的所有文件
这与:
(directory "/Lisp/cl-http/cl-http-342/server/md5.*")
它较短,但取决于Unix路径名语法。实现目录列表的现代公共Lisp库是 它的工作原理如下:
CL-USER> (iolib.os:list-directory "/etc/apt")
(#/p/"trusted.gpg~" #/p/"secring.gpg" #/p/"trustdb.gpg" #/p/"sources.list"
#/p/"sources.list~" #/p/"apt-file.conf" #/p/"apt.conf.d" #/p/"trusted.gpg"
#/p/"sources.list.d")
请注意,不需要尾随斜杠或通配符。它非常健壮,甚至可以处理编码错误的unicode字符的文件名
与CL-FAD相比的差异:
- 您得到的对象是IOLIB文件路径,它替代了CL的路径名,而CL的路径名更接近底层操作系统的功能
- IOLIB使用CFFI实现它的例程,因此它在所有Lisp实现上都是一样的(前提是IOLIB有一个操作系统的后端),与CL-FAD相反,CL-FAD试图用它所有的怪癖来抽象实现的目录函数
- 与CL-FAD相反,iolib正确处理符号链接(CL-FAD的一个主要问题是它在Windows IMHO以外的平台上几乎不可用)
uiop:directory files
。str:contains?可通过搜索
完成
;; searching for "ref".
(setf *data-directory* "~/books/lisp")
(remove-if-not (lambda (it)
(str:contains? "ref" (namestring it)))
(osicat:list-directory *data-directory*))
返回
(#P"~/books/lisp/common-lisp-quick-reference-clqr-a4-booklet-all.pdf"
#P"~/books/lisp/common-lisp-quick-reference-clqr-a4-consec.pdf"
#P"~/books/lisp/commonLisp-interactive-approach-reference-buffalo.pdf")
如果能正确使用通配符,这当然是可以改进的
参考资料:
;; searching for "ref".
(setf *data-directory* "~/books/lisp")
(remove-if-not (lambda (it)
(str:contains? "ref" (namestring it)))
(osicat:list-directory *data-directory*))
(#P"~/books/lisp/common-lisp-quick-reference-clqr-a4-booklet-all.pdf"
#P"~/books/lisp/common-lisp-quick-reference-clqr-a4-consec.pdf"
#P"~/books/lisp/commonLisp-interactive-approach-reference-buffalo.pdf")