这是一个后续问题 在 MacBook 中使用 Common Lisp 创建名称中带有方括号的文件会产生问题。我该怎么办?
这是我自己回答的,因为 ChatGPT 给了我答案。
但是在尝试解压缩 Excel 文件(其中包含名称中带有方括号的“[Content_Type].xml”文件)的过程中,这会产生问题, 我意识到
zip
库 - 及其 unzip
函数在解压缩这个方括号名称时也存在问题。
unzip函数的源代码在这里https://github.com/mcna/zip/blob/master/zip.lisp 它是这样的:
(defun unzip (pathname target-directory &key (if-exists :error) verbose)
;; <Xof> "When reading[1] the value of any pathname component, conforming
;; programs should be prepared for the value to be :unspecific."
(when (set-difference (list (pathname-name target-directory)
(pathname-type target-directory))
'(nil :unspecific))
(error "pathname not a directory, lacks trailing slash?"))
(with-zipfile (zip pathname)
(do-zipfile-entries (name entry zip)
(let ((filename (merge-pathnames name target-directory)))
(ensure-directories-exist filename)
(unless (char= (elt name (1- (length name))) #\/)
(ecase verbose
((nil))
((t) (write-string name) (terpri))
(:dots (write-char #\.)))
(force-output)
(with-open-file
(s filename :direction :output :if-exists if-exists
:element-type '(unsigned-byte 8))
(zipfile-entry-contents entry s)))))))
我们来看一个 Excel 文件。 并使用此功能解压缩它。 我手动创建了一个 Excel 文件。然后指定它的路径:
(defparameter *xlsx* "/Users/<user-name>/Downloads/test.xlsx")
(ql:quickload :zip)
(zip:unzip *xlsx* "/Users/<user-name>/Downloads/test_zip/")
它与我在上一篇文章中遇到的问题完全相同。
bad place for a wild pathname
[Condition of type SB-INT:SIMPLE-FILE-ERROR]
Restarts:
0: [RETRY] Retry SLY mREPL evaluation request.
1: [*ABORT] Return to SLY's top level.
2: [ABORT] abort thread (#<THREAD tid=5123 "sly-channel-1-mrepl-remote-1" RUNNING {70051404E3}>)
Backtrace:
0: (SB-KERNEL::%FILE-ERROR #P"/Users/<user-name>/Downloads/test_zip/[Content_Types].xml" "bad place for a wild pathname")
Locals:
ARGUMENTS = NIL
DATUM = "bad place for a wild pathname"
PATHNAME = #P"/Users/<user-name>/Downloads/test_zip/[Content_Types].xml"
1: (ENSURE-DIRECTORIES-EXIST #P"/Users/<user-name>/Downloads/test_zip/[Content_Types].xml" :VERBOSE NIL :MODE 511)
Locals:
#:.DEFAULTING-TEMP. = NIL
#:.DEFAULTING-TEMP.#1 = 511
SB-IMPL::CREATED-P = NIL
PATHNAME = #P"/Users/<user-name>/Downloads/test_zip/[Content_Types].xml"
SB-IMPL::PATHSPEC = #P"/Users/<user-name>/Downloads/test_zip/[Content_Types].xml"
2: (ZIP:UNZIP "/Users/josephus/Downloads/test.xlsx" "/Users/<user-name>/Downloads/test_zip/" :IF-EXISTS :ERROR :VERBOSE NIL :FORCE-UTF-8 NIL)
Locals:
#:.DEFAULTING-TEMP. = NIL
FILENAME = #P"/Users/<user-name>/Downloads/test_zip/[Content_Types].xml"
FORCE-UTF-8 = NIL
IF-EXISTS = :ERROR
PATHNAME = "/Users/<user-name>/Downloads/test.xlsx"
TARGET-DIRECTORY = "/Users/josephus/Downloads/test_zip/"
ZIP = #S(ZIP:ZIPFILE :STREAM #<SB-SYS:FD-STREAM for "file /Users/<user-name>/Downloads/test.xlsx" {700888DB43}> :ENTRIES #<HASH-TABLE :TEST EQUAL :COUNT 11 {70088A23A3}>)
3: (SB-INT:SIMPLE-EVAL-IN-LEXENV (ZIP:UNZIP *XLSX* "/Users/<user-name>/Downloads/test_zip/") #<NULL-LEXENV>)
4: (EVAL (ZIP:UNZIP *XLSX* "/Users/<user-name>/Downloads/test_zip/"))
5: ((LAMBDA NIL :IN SLYNK-MREPL::MREPL-EVAL-1))
有人知道如何处理吗?
我问了chatGPT,它建议:
(defun better-unzip (pathname target-directory &key (if-exists :error) verbose)
"Unzip function that handles square brackets in filenames correctly."
(zip:with-zipfile (zip pathname)
(zip:do-zipfile-entries (name entry zip)
(let ((filename (make-pathname :directory target-directory
:name (pathname-name (parse-namestring name))
:type (pathname-type (parse-namestring name)))))
(ensure-directories-exist filename)
(unless (char= (elt name (1- (length name))) #\/)
(ecase verbose
((nil))
((t) (write-string name) (terpri))
(:dots (write-char #\.)))
(force-output)
(with-open-file (s filename :direction :output :if-exists if-exists
:element-type '(unsigned-byte 8))
(zip:zipfile-entry-contents entry s)))))))
然后我做了:
(better-unzip *xlsx* "/Users/<your-user-name>/Downloads/test_zip/")
但是我又遇到了:
bad place for a wild pathname
[Condition of type SB-INT:SIMPLE-FILE-ERROR]
Restarts:
0: [RETRY] Retry SLY mREPL evaluation request.
1: [*ABORT] Return to SLY's top level.
2: [ABORT] abort thread (#<THREAD tid=5123 "sly-channel-1-mrepl-remote-1" RUNNING {70051404E3}>)
Backtrace:
0: (SB-KERNEL::%FILE-ERROR #P"//Users/<user-name>/Downloads/test_zip//[Content_Types].xml" "bad place for a wild pathname")
1: (ENSURE-DIRECTORIES-EXIST #P"//Users/<user-name>/Downloads/test_zip//[Content_Types].xml" :VERBOSE NIL :MODE 511)
2: (BETTER-UNZIP "/Users/josephus/Downloads/test.xlsx" "/Users/<user-name>/Downloads/test_zip/" :IF-EXISTS :ERROR :VERBOSE NIL)
3: (SB-INT:SIMPLE-EVAL-IN-LEXENV (BETTER-UNZIP *XLSX* "/Users/<user-name>/Downloads/test_zip/") #<NULL-LEXENV>)
4: (EVAL (BETTER-UNZIP *XLSX* "/Users/<user-name>/Downloads/test_zip/"))
5: ((LAMBDA NIL :IN SLYNK-MREPL::MREPL-EVAL-1))
我会打电话
(ensure-directories-exist "/Users/foo/dir/")
而不是
(ensure-directories-exist "/Users/foo/dir/[a].b")