Common lisp 如何在Common Lisp中搜索带有通配符的文件?
我不满意找到与以下字符串匹配的文件:Common lisp 如何在Common Lisp中搜索带有通配符的文件?,common-lisp,wildcard,pathname,Common Lisp,Wildcard,Pathname,我不满意找到与以下字符串匹配的文件: (remove-if-not (lambda (it) (search "wildcard" (namestring it))) (uiop:directory-files "./")) ;; I'll ignore case with str:contains? ;; https://github.com/vindarel/cl-str 如何使用unix样式的通配符搜索文件 如果不是内置
(remove-if-not (lambda (it)
(search "wildcard" (namestring it)))
(uiop:directory-files "./"))
;; I'll ignore case with str:contains?
;; https://github.com/vindarel/cl-str
如何使用unix样式的通配符搜索文件
如果不是内置的,我会喜欢一个解决方案。可能有with或(看起来不是这样,文档经常说“非野生路径名”)
如果可以使用双通配符递归遍历目录(/***/.jpg
),则可获得额外奖励
edit:我尝试了(directory#p./***.jpg)的变体
,它返回nil:(也尝试了#p.*jpg”
,#p./*jpg”
(wild-pathname-p (pathname "*.jpg"))
(:WILD :WILD-INFERIORS)
(make-pathname :name :wild :type "jpg")
#P"*.jpg"
以下内容通过jpg扩展名获取文件,但它还不是一个合适的通配符:
(directory *)
(#P"/home/vince/cl-cookbook/AppendixA.jpg"
#P"/home/vince/cl-cookbook/AppendixB.jpg"
#P"/home/vince/cl-cookbook/AppendixC.jpg")
关于路径名和生成路径名的文档
:(未提及通配符)SBCL
SBCL支持名称中的通配符。首先,创建一些文件:
(loop
with stem = #P"/tmp/stack/_.txt"
initially (ensure-directories-exist stem)
for name in '("abc" "def" "cadar" "cdadr" "cddr")
for path = (make-pathname :name name :defaults stem)
do (open path :direction :probe :if-does-not-exist :create))
然后,列出包含“a”的所有文件:
路径名包含特定于实现的(有效)名称组件:
CL-USER> (describe #P"/tmp/stack/*a*.txt")
#P"/tmp/stack/*a*.txt"
[structure-object]
Slots with :INSTANCE allocation:
HOST = #<SB-IMPL::UNIX-HOST {10000F3FF3}>
DEVICE = NIL
DIRECTORY = (:ABSOLUTE "tmp" "stack")
NAME = #<SB-IMPL::PATTERN :MULTI-CHAR-WILD "a" :MULTI-CHAR-WILD>
TYPE = "txt"
VERSION = :NEWEST
; No value
…其中,通配符
可能基于regex():
(注意:上面的负回望不能消除转义的反斜杠)
中间职能:
CL-USER> (parse-wildcard "*a*a\\*a?\\?a")
(:WILD "a" :WILD "a\\*a" :CHAR "\\?a")
CL-USER> (wildcard-regex (parse-wildcard "*a*a\\*a?\\?a"))
(:SEQUENCE :START-ANCHOR #1=(:GREEDY-REPETITION 0 NIL :EVERYTHING) "a" #1# "a\\*a" :EVERYTHING "\\?a" :END-ANCHOR)
没有当前目录和主目录字符
CL-USER 46 > (directory "/bin/*")
(#P"/bin/[" #P"/bin/bash" #P"/bin/cat" .... )
表示当前目录的
概念在portable Common Lisp中不存在。这可能存在于特定的文件系统和特定的实现中
另外,~
表示主目录不存在。某些实现可能会将它们识别为不可移植的扩展
在路径名字符串中,有*
和**
作为通配符。这适用于绝对和相对路径名
默认路径名的默认值
Common Lisp具有*默认路径名默认值*
,它为某些路径名操作提供了默认值
示例
CL-USER 46 > (directory "/bin/*")
(#P"/bin/[" #P"/bin/bash" #P"/bin/cat" .... )
现在,在上面的内容中,它已经有点未定义或与Unix上的实现有所不同:
- 解析符号链接
- 是否包含“隐藏”文件
- 包含类型为的文件
CL-USER 48 > (let ((*default-pathname-defaults* (pathname "/bin/")))
(directory "*sh"))
(#P"/bin/zsh" #P"/bin/tcsh" #P"/bin/sh" #P"/bin/ksh" #P"/bin/csh" #P"/bin/bash")
主目录中的文件:
CL-USER 49 > (let ((*default-pathname-defaults* (user-homedir-pathname)))
(directory "*"))
同样:
CL-USER 54 > (directory (make-pathname :name "*"
:defaults (user-homedir-pathname)))
在/usr/local/
及以下文件中查找以sh结尾的所有文件:
CL-USER 54 > (directory "/usr/local/**/*sh")
使用MAKE-PATHNAME构建路径名
查找/usr/local/
下所有.h
文件的三种方法:
(directory "/usr/local/**/*.h")
(directory (make-pathname :name :wild
:type "h"
:defaults "/usr/local/**/")
(directory
(make-pathname :name :wild
:type "h"
:directory '(:ABSOLUTE "usr" "local" :WILD-INFERIORS)))
问题
CL-USER 46 > (directory "/bin/*")
(#P"/bin/[" #P"/bin/bash" #P"/bin/cat" .... )
跨平台(“windows”、“unix”、“mac”和“…”)甚至在同一平台(尤其是“windows”或“unix”)上的实现有很多不同的解释。路径名中的unicode之类的东西会增加复杂性—在CL标准中没有描述
我们仍然有很多不同的文件系统(),但它们的功能与设计Common Lisp时的典型功能不同。实现可能跟踪了这些更改,但不一定是以可移植的方式进行的。如果执行
(wild-pathname-p(pathname“*.jpg”)
?那么(make pathname:name:wild:type“jpg”)
?那么(directory#p./***.jpg)呢?
?我通过更新我的问题来回答。(directory…
返回零,(directory(make pathnam…:type“jpg”)
有效。这可能适用于某些路径名。路径名在Lisp中很难使用,因为api的设计足够通用,可以适应20世纪80年代中期的所有操作系统,但这意味着unix路径名的每个CL实现都略有不同。我仍然会寻找一种可移植的方法来o如果我是你,我确实不知道有一个.SBCL。你能举个例子吗?谢谢。但是我不能让以下内容返回sthg:(directory#P)/tmp/stack/*a.*)
,我试过使用regexp变量。看起来我们必须指定扩展名,不仅是txt
,而且.txt
,以下也不起作用:(directory#P)/tmp/stack/*a*txt)
@Ehvince如有疑问,请使用描述查看字符串如何解析为路径名对象。第一个查找名称组件以点开头,以“a”结尾的文件其类型为wild。语法可能与我们在使用linux时的预期不符。谢谢。您的示例涉及通配符+文件扩展名。您有没有方法在不精确扩展名的情况下搜索包含字符串的文件?
CL-USER 54 > (directory (make-pathname :name "*"
:defaults (user-homedir-pathname)))
CL-USER 54 > (directory "/usr/local/**/*sh")
(directory "/usr/local/**/*.h")
(directory (make-pathname :name :wild
:type "h"
:defaults "/usr/local/**/")
(directory
(make-pathname :name :wild
:type "h"
:directory '(:ABSOLUTE "usr" "local" :WILD-INFERIORS)))