2009-09-10 5 views
22

내가 다윈에 OpenMCL를 사용하고, 나는 같은 것을 할 싶습니다Common Lisp의 디렉토리를 반복하는 방법은 무엇입니까?

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

을하지만 NIL 이외의 아무것도 반환하는 directory를 얻을 수 없다, 나는 어떤을 찾을 수 없습니다 좋은 설명 온라인 ("각 시스템마다 다름"제외).

모든 포인터?

답변

16

경로 이름 사양에 와일드 카드가 포함되어 있습니까? 커먼 리스프의 경로 물건은 처음에는 이해하기 다소 어렵다 - 적어도 나에게 그게 말이지 ... CLHS 상태 이름으로 directory 기능에 :

pathspec 야생없는 경우, 결과 목록이 포함됩니다 중 0 개 또는 하나의 요소 내가 큰 도움이 CL-FAD 라이브러리를 발견

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

심지어

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

처럼

와일드 카드를 포함, 당신은 메이크업 경로 기능을 시도 할 수 있습니다 귀하의 경로를하기 위해, 경로명과 파일 시스템을 다루기 위해서. 특히 list-directory 기능은 일반 표준 directory 기능보다 사용하기가 더 쉽습니다. 문자열은 분명 플랫폼에 따라 있습니다

  • 하여 문자열

: 예를 들어 윈도우 구문 대 유닉스 구문

+2

이 - (디렉토리 "경로 이름") NIL을, (디렉토리 반환 "pathname /*.*")는 나에게 예상 된 결과를 주었다. – Justicle

+1

점에 이름이있는 파일 만 필요합니까? – Svante

+0

이상한가? 나는 실제로 .h와 .cpp 파일 뒤에 있지만 "pathname/*"는 NIL을 반환합니다. – Justicle

26

는 기본적으로 경로 이름을 지정하는 방법은 두 가지가 있습니다.

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

그래서 내부적으로 커먼 리스프는 경로 객체와 작동하지만, 정상적인 문자열을 사용할 수 있도록하고 필요한 경우 그들로부터 경로 객체를 만든다.

CL의이 (디렉토리가없는 예를 들어) 지정된 모든 성분을 갖는 경로를보고, 그런 다음 * variabel * 기본적 경로명 디폴트 값인 경로 객체의 구성 요소에 채운다.리습 함수를 만드는 경로가

MAKE-경로 이름을 개체를 사용하여

? (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 
  • : 함수와

    는 경로 이름 (여기 Clozure CL)의 구성 요소를 볼 수 DESCRIBE 함수이며 구성 요소를 지정하기 위해 몇 가지 키워드 인수가 필요합니다.

    때때로 또한 기존 기반으로 새 경로를 생성하는 데 유용합니다 :

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

    당신이 전화 번호부를 사용하는 경우는 와일드 카드 경로 이름을 사용하는 것이 유용합니다. DIRECTORY는 일치하는 경로 이름 목록을 리턴합니다. 'DIRECTORY'라는 이름은 디렉토리의 내용을 나열하지 않지만 와일드 카드로 경로 이름 (일반적으로)에 일치하는 경로 이름을 나열하기 때문에 약간 오도 된 것입니다. 와일드 카드는 /foo/s*c/list*.l*와 같은 구성 요소의 문자 시퀀스와 일치 할 수 있습니다./foo/**와 같은 디렉토리 계층의 일부와 일치시키는 데 사용되는 와일드 카드 **도 있습니다 /test.lisp, 이는 디렉토리 foo에와 그 하위 디렉토리 아래에있는 모든 파일을 test.lisp 일치합니다.

    (directory "/Users/foo/Lisp/**/*.lisp") 
    
    위는 '/ 사용자/foo는/리스프 /'모두의 모든 'LISP'파일의 목록을 반환해야

    하위 디렉토리

    단일 디렉토리 사용중인 .c 인 파일을 반환하려면 다음. 다이어 그

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

    주 CTORY는 경로명 객체 목록을 반환합니다 (문자열 목록이 아닙니다).

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

    하지만 유닉스 경로 구문에 따라 달라진다.

+0

+1 LISP에서 경로 이름을 요약하면 매우 유용합니다. – Justicle

8

디렉토리 목록을 구현하는 최신 Common Lisp 라이브러리는 IOLIB입니다.

그것은 다음과 같이 작동 후행 슬래시 또는 와일드 카드가 필요하지 않습니다

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 파일 경로, 가까운 기본 OS가하는 일입니다 CL의 경로 이름을 대체합니다.
  • IOLIB는 CFFI를 사용하여 루틴을 구현하므로 모든 Lisp 구현에서 동일하게 작동합니다 (IOLIB에 운영 체제에 대한 백엔드가있는 경우). CL-FAD와 달리 구현의 DIRECTORY 함수를 버릇.
  • CL-FAD와는 달리 iolib는 심볼릭 링크를 올바르게 처리합니다 (CL-FAD의 주요 문제점 중 하나 인 Windows IMHO 이외의 플랫폼에서 실제로 사용할 수 없게 됨).
1

코드 스 니펫 (code snippet)을 위해 저에게 적합한 예제를 추가하겠습니다. 나는 osicat (cl-fad와 유사)과 str을 사용합니다.

편집 : uiop:directory-files도 있습니다. str : contains? 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") 

는 확실히 와일드 카드의 내 적절한 사용을 향상시킬 수있다. 그러나 그것은 지금 당신이 사용할 수있는 코드 조각입니다 :)

참고 :

관련 문제