Вопрос

Я использую OpenMCL в Дарвине и хотел бы сделать что-то вроде:

(loop for f in (directory "somedir")
  collect (some-per-file-processing f))

Но я не могу получить directory вернуть что-либо, кроме NIL, и я не могу найти в Интернете какого-либо хорошего объяснения (кроме «для каждой системы оно разное»).

Есть какие-нибудь указатели?

Это было полезно?

Решение

Содержит ли ваша спецификация пути подстановочный знак? Путь к путевым именам Common Lisp поначалу довольно сложно понять - по крайней мере, для меня это было так ... CLHS сообщает о функции directory :

  

Если pathspec не является диким,   итоговый список будет содержать либо   ноль или один элемент.

Чтобы ваш путь к файлу включал подстановочный знак, вы можете попробовать функцию make-pathname, например

(directory (make-pathname :directory '(:absolute "srv" "hunchentoot") :name :wild :type "lisp"))

Или даже

(directory (make-pathname :directory '(:absolute "srv" "hunchentoot") :name :wild :type :wild))

Я обнаружил, что библиотека CL-FAD очень полезна для работы с именами путей и файловой системой. , В частности, его функция list-directory может быть проще использовать, чем простая стандартная функция directory .

Другие советы

Есть два основных способа указать пути:

  • использование строк

Строки, очевидно, зависят от платформы:Синтаксис Unix против.Синтаксис Windows, например.

"/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 гарантирует, что при обратном чтении создается объект пути (а не строка).

? #P"/Users/bar/foo.text"
#P"/Users/bar/foo.text"

Итак, Common Lisp внутренне работает с объектами пути, но позволяет использовать обычные строки и при необходимости создавать из них объекты пути.

Когда Common Lisp видит путь, в котором указаны не все компоненты (например, отсутствует каталог), он заполняет компоненты из объекта пути, который является значением переменной *DEFAULT-PATHNAME-DEFAULTS* .

С помощью функции DESCRIBE вы можете просмотреть компоненты пути (здесь Clozure CL):

? (describe (pathname "/Users/bar/*.text"))
#P"/Users/bar/*.text"
Type: PATHNAME
Class: #<BUILT-IN-CLASS PATHNAME>
TYPE: (PATHNAME . #<CCL::CLASS-WRAPPER PATHNAME #x3000401D03BD>)
%PATHNAME-DIRECTORY: (:ABSOLUTE "Users" "bar")
%PATHNAME-NAME: :WILD
%PATHNAME-TYPE: "text"
%PHYSICAL-PATHNAME-VERSION: :NEWEST
%PHYSICAL-PATHNAME-DEVICE: NIL
  • использование функций Lisp для создания объектов пути

MAKE-PATHNAME — это функция, которая требует нескольких ключевых аргументов для указания компонентов.

Иногда также полезно создать новый путь на основе существующего:

(make-pathname :name "foo" :defaults (pathname "/Users/bar/baz.text"))

Если вы используете DIRECTORY, полезно использовать путь с подстановочными знаками. DIRECTORY затем вернет список совпадающих имен путей.Имя «DIRECTORY» немного вводит в заблуждение, поскольку DIRECTORY не перечисляет содержимое каталога, а перечисляет соответствующие пути (обычно) с подстановочными знаками.Подстановочные знаки могут соответствовать последовательностям символов в таких компонентах, как /foo/s*c/list*.l*".Существует также подстановочный знак **, который используется для сопоставления частей иерархии каталогов, например /foo/**/test.lisp, который соответствует всем файлам test.lisp в каталоге foo и его подкаталогах.

(directory "/Users/foo/Lisp/**/*.lisp")

Выше должен быть возвращен список всех файлов «lisp» в «/Users/foo/Lisp/» и всех его подкаталогах.

Чтобы вернуть файлы .c в один каталог, используйте:

(directory "/Users/foo/c/src/*.c")

Обратите внимание, что DIRECTORY возвращает список объектов пути (а не список строк).

? (directory (make-pathname
               :name "md5"
               :type :wild
               :directory '(:absolute "Lisp" "cl-http" "cl-http-342" "server")))
(#P"/Lisp/cl-http/cl-http-342/server/md5.lisp"
 #P"/Lisp/cl-http/cl-http-342/server/md5.xfasl")

Выше используется объект пути, созданный MAKE-PATHNAME.Он возвращает все файлы, соответствующие /Lisp/cl-http/cl-http-342/server/md5.* .

Это то же самое, что:

(directory "/Lisp/cl-http/cl-http-342/server/md5.*")

который короче, но зависит от синтаксиса пути Unix.

Современная библиотека Common 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")

Обратите внимание, что косая черта или подстановочные знаки не требуются.Он очень надежен и может даже обрабатывать имена файлов с неправильно закодированными символами Юникода.

Отличия от CL-FAD:

  • Объекты, которые вы получаете, — это пути к файлам IOLIB, замена имен путей CL, которая ближе к тому, что делает базовая ОС.
  • IOLIB реализует свои процедуры с использованием CFFI, поэтому он работает одинаково во всех реализациях Lisp (при условии, что IOLIB имеет серверную часть для операционной системы), в отличие от CL-FAD, который пытается абстрагироваться от функции DIRECTORY реализации со всеми ее причудами.
  • В отличие от CL-FAD, iolib правильно обрабатывает символические ссылки (одна серьезная проблема с CL-FAD, которая делает его практически непригодным для использования на платформах, отличных от Windows, ИМХО).

Я добавлю пример, который работает для меня, ради фрагмента кода.я использую осикат (аналог cl-fad) и ул..

редактировать:также с uiop:directory-files.ул: содержит?можно было бы сделать с search.

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

Конечно, это можно улучшить за счет правильного использования подстановочных знаков.Однако этот фрагмент вы можете использовать прямо сейчас:)

Использованная литература:

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top