我不满意找到匹配字符串的文件:
(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样式的通配符搜索文件?
如果它不是内置的,我会享受uiop的解决方案。也许有Osicat或cl-fad(它似乎并非如此,文档经常说"非野生路径名")。
如果可以使用双通配符递归遍历目录(./**/*.jpg
),则获得奖励。
修改:我尝试了(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")
路径名和make-pathname
的文档:http://gigamonkeys.com/book/files-and-file-io.html(未提及通配符)
答案 0 :(得分:7)
SBCL支持名称中的通配符。首先,创建一些文件:
{
market_hash_name: price,
market_hash_name: price.. etc
}
然后,列出包含“a”的所有文件:
Object.keys(data).length === 30000
路径名包含特定于实现的(有效)名称组件:
(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))
SBCL还定义了CL-USER> (directory #P"/tmp/stack/*a*.txt")
(#P"/tmp/stack/abc.txt" #P"/tmp/stack/cadar.txt" #P"/tmp/stack/cdadr.txt")
,它逐个处理文件,而不是先收集列表中的所有文件。
如果您需要坚持使用标准路径名组件,可以先使用普通通配符调用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
,然后过滤生成的列表:
sb-ext:map-directory
...其中directory
可能基于正则表达式(PPCRE):
CL-USER> (remove-if-not (wildcard "*a*")
(directory #P"/tmp/stack/*.txt")
:key #'pathname-name)
(#P"/tmp/stack/abc.txt" #P"/tmp/stack/cadar.txt" #P"/tmp/stack/cdadr.txt")
(注意:上面的负面反馈会不消除转义的反斜杠)
wildcard
中级职能:
(defun parse-wildcard (string)
(delete ""
(map 'list
(lambda (string)
(or (cdr (assoc string
'(("*" . :wild)
("?" . :char))
:test #'string=))
string))
(ppcre:split '(:sequence
(:negative-lookbehind #\\)
(:register (:alternation #\* #\?)))
string
:with-registers-p t))
:test #'string=))
答案 1 :(得分:5)
没有当前目录且没有主目录字符
便携式Common Lisp中不存在表示当前目录的.
概念。这可能存在于特定的文件系统和特定的实现中。
同样~
表示主目录不存在。某些实现可能会将它们识别为非可移植扩展。
在路径名字符串中,您有*
和**
作为通配符。这适用于绝对路径名和相对路径名。
默认路径名的默认值
Common Lisp有*default-pathname-defaults*
,它为某些路径名操作提供了默认值。
<强>实施例强>
CL-USER 46 > (directory "/bin/*")
(#P"/bin/[" #P"/bin/bash" #P"/bin/cat" .... )
现在在上面已经略微未定义或分散了Unix上的实现:
下一步:
CL-USER 47 > (directory "/bin/*sh")
(#P"/bin/zsh" #P"/bin/tcsh" #P"/bin/sh" #P"/bin/ksh" #P"/bin/csh" #P"/bin/bash")
使用相对路径名:
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构建路径名
在.h
下找到所有/usr/local/
个文件的三种方法:
(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)))
<强>问题强>
跨平台('windows','unix','mac',...)甚至在同一平台(尤其是'windows'或'unix')上有很多不同的实现解释。像路径名中的unicode这样的东西会产生额外的复杂性 - 而不是在CL标准中描述。
我们仍然有很多不同的文件系统(https://en.wikipedia.org/wiki/List_of_file_systems),但它们的功能与Common Lisp设计时的典型不同或不同。实现可能已经跟踪了这些变化,但不一定是以便携式方式。