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)))