2009-09-10 13 views
22

Ben Darwin OpenMCL kullanıyorum ve ben böyle bir şey yapmak istiyorum:Common Lisp'te bir dizinde nasıl yineleyebilirim?

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

Ama NIL dışında başka bir şey dönmek için directory alamayan ve herhangi bulmak gibi olamaz iyi bir açıklama çevrimiçi ("her sistem için farklı").

İşaretçiler var mı?

cevap

16

Yol adı belirtiminiz bir joker karakter içeriyor mu? Ortak Lisp'in yol adı şeyler ilk başta kavramak biraz zor - en azından benim için öyleydi ... CLHS devletler olarak directory fonksiyonu üzerine:

pathspec vahşi değilse, çıkan liste içerecektir ya sıfır veya bir eleman. Ben büyük bir yardım CL-FAD kütüphane bulundu

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

Hatta

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

gibi

bir joker ekleyin, make-yol adı işlevini deneyebilirsiniz senin yol adı olması amacıyla, Yol adları ve dosya sistemi ile ilgili. Özellikle, list-directory işlevinin kullanımı, standart directory işlevinden daha kolay olabilir. Dizeler açıkçası platformuna bağlı olan

  • kullanarak dizeleri

: Örneğin, Windows sözdizimi vs Unix sözdizimi

+2

- (dizin "yol adı") nil, (dizin döndü "pathname /*.*") bana beklenen sonuçları verdi. – Justicle

+1

Sadece nokta içeren isimlere ihtiyacınız var mı? – Svante

+0

Garip ha? Aslında .h ve .cpp dosyalarının peşindeyim, ancak "pathname/*" NIL değerini döndürüyor. – Justicle

26

temelde pathnames belirtmek için iki yol vardır.

"/Users/foo/bar.text" is a valid pathname 
"/Users/foo/*/foo.*" is a valid pathname with two wildcards 

Bir dizeden bir yol adı nesnesi oluşturabilirsiniz:

? (pathname "/Users/bar/foo.text") 
#P"/Users/bar/foo.text" 

#p üstünde bir yol adı nesne (ve bir dize) oluşturulur olmasını sağlar, geri okuyunca.

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

Yani, içten Common Lisp yol adı nesnelerle çalışır, ancak normal dizeleri kullanmanızı sağlar ve gerekirse onlardan yol adı nesneleri yapar.

Ortak Lisp, belirtilen tüm bileşenlerin (örneğin dizin eksik) olan bir yol adını gördüğünde, bu durumda, bileşenler içindeki değerlerin değeri olan pathname nesnesinin * DEFAULT-PATHNAME-DEFAULTS * değerini doldurur.Lisp fonksiyonlar oluşturarak yol adı

BÜTÜNLEME yol adını nesneleri kullanarak

? (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 
  • : Bu fonksiyonla

    bir yol adı (burada Clozure CL) bileşenleri bakabilirsiniz DESCRIBE işlevdir ve bileşenleri belirtmek için birkaç anahtar kelime argümanını alır.

    Bazen de mevcut bir dayalı yeni bir yol adı oluşturmak için yararlıdır:

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

    Eğer DIRECTORY kullanırsanız, joker karakterler ile bir yol adı kullanmak yararlı olur. DIRECTORY daha sonra eşleşen yol adlarının bir listesini döndürecektir. DIRECTORY bir dizinin içeriğini listelemediğinden, 'DIRECTORY' adı biraz yanıltıcıdır, ancak (genellikle) joker karakterleri olan bir yol adı için eşleşen yol adlarını listeler. Joker karakterler, /foo/s*c/list*.l* gibi bileşenlerin karakter dizileriyle eşleşebilir. Ayrıca, bir hiyerarşinin/foo/gibi bir dizinin parçalarını eşleştirmek için kullanılan vahşi kart ** da vardır. /test.lisp, hangi dizinin foo ve alt dizinlerinde altındaki tüm dosyaları test.lisp eşleşir.

    (directory "/Users/foo/Lisp/**/*.lisp") 
    
    Üstü '/ Users/foo/Lisp /' ve sonuçta 'lisp' dosyaların bir listesini dönmelidir

    altdizinleri

    tek dizininin kullanımda .c dosyaları dönmek için:. DIRE o

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

    Not CTORY, bir yol adı nesnesi listesi döndürür (dizelerin bir listesi değil).

    ? (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") 
    

    Yukarıda, MAKE-PATHNAME tarafından oluşturulan bir pathname nesnesi kullanılır. /Lisp/cl-http/cl-http-342/server/md5.* ile eşleşen tüm dosyaları döndürür.

    Bu aynı: kısadır

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

    ancak Unix yol adı sözdizimi bağlıdır.

+0

+ 1 LISP'deki yol adlarının iyi bir özeti, çok yararlı. – Justicle

8

Dizini listeleyen modern Common Lisp kitaplığı IOLIB'dur.

Bu gibi çalışır: hayır eğik çizgi veya joker gereklidir

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

Not söyledi. Çok sağlam ve yanlış kodlanmış unicode karakterleriyle dosya isimlerini bile işleyebilir. CL-FAD kıyasla

Farklılıklar: Alacağınız

  • nesneler IOLIB dosya yolları, yakın plandaki işletim yaptığı iştir CL en pathnames yerini bulunmaktadır.
  • IOLIB, rutinlerini CFFI kullanarak uygular, böylece tüm Lisp uygulamalarında aynı şekilde çalışır (IOLIB işletim sistemine yönelik bir arka plan sağladıysa), CL-FAD'in tersine, uygulamanın tümüyle DIRECTORY işlevi üzerinde soyutlamaya çalışır. quirks.
  • CL-FAD'den farklı olarak, iolib doğru bağlantılarla ilgilenir (CL-FAD ile ilgili önemli bir sorun, Windows IMHO dışındaki platformlarda neredeyse kullanılamaz hale getirir).
1

Kod snippet'i için benim için çalışan bir örnek ekleyeceğim. osicat (cl-fad'a benzer) ve str kullanıyorum.

düzenleme: ayrıca uiop:directory-files ile. str: içeriyor? search ile yapılabilir.

;; searching for "ref". 
(setf *data-directory* "~/books/lisp") 
(remove-if-not (lambda (it) 
        (str:contains? "ref" (namestring it))) 
       (osicat:list-directory *data-directory*)) 

döner

(#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") 

Kesinlikle wildcard'ların benim bir doğru kullanımını geliştirilebilir. Ancak şu an kullanabileceğiniz bir parçacık İşte:)

Referanslar:

İlgili konular