더 많은 경로 유틸리티

더 많은 경로 유틸리티 (More Path Utilities)

경로 이름을 다룰 때 쓰는 추가 유틸리티들을 살펴볼게요. 확장자 추출, 상대 경로 찾기, 경로 정규화 등 실무에서 자주 필요한 함수들이 모여 있어요.

출처: Racket Reference

본문

(require racket/path)  |  package: base

이 절에 문서화된 바인딩들은 racket/pathracket 라이브러리가 제공하는 것이지, racket/base가 제공하는 게 아니에요.

procedure

(file-name-from-path path) → (or/c path-for-some-system? #f)
  path : (or/c path-string? path-for-some-system?)

path의 마지막 요소를 돌려줘요. path가 구문적으로 디렉터리 경로라면(split-path 참고), 결과는 #f예요.

procedure

(path-get-extension path) → (or/c bytes? #f)
  path : (or/c path-string? path-for-some-system?)

path 안 파일 이름의 확장자 부분(분리자 .를 포함)인 바이트 문자열을 돌려줘요. 경로에 확장자가 없으면 #f를 돌려줘요.

파일 이름 확장자의 정의는 path-replace-extension을 참고하세요.

예시를 볼게요:

> (path-get-extension "x/y.rkt")
#".rkt"
> (path-get-extension "x/y")
#f
> (path-get-extension "x/y.tar.gz")
#".gz"
> (path-get-extension "x/.racketrc")
#f

패키지 base의 버전 6.5.0.3에서 추가됨.

procedure

(path-has-extension? path ext) → boolean?
  path : (or/c path-string? path-for-some-system?)
  ext : (or/c bytes? string?)

path의 마지막 요소가 ext로 끝나되 ext와 정확히 같지는 않은지 판별해요.

ext가 확장자 모양의 바이트 문자열이면(즉 .로 시작하고 다른 .를 포함하지 않으면), 이 검사는 (path-get-extension path)ext를 만들어 내는지 확인하는 것과 동등해요.

예시를 볼게요:

> (path-has-extension? "x/y.rkt" #".rkt")
#t
> (path-has-extension? "x/y.ss" #".rkt")
#f
> (path-has-extension? "x/y" #".rkt")
#f
> (path-has-extension? "x/.racketrc" #".racketrc")
#f
> (path-has-extension? "x/compiled/y_rkt.zo" #"_rkt.zo")
#t

패키지 base의 버전 6.5.0.3에서 추가됨.

procedure

(filename-extension path) → (or/c bytes? #f)
  path : (or/c path-string? path-for-some-system?)

참고: 이 함수는 폐기(deprecated)됐어요. 대신 path-get-extension을 쓰세요.

path 안 파일 이름의 확장자 부분(분리자 . 없이)인 바이트 문자열을 돌려줘요. path가 구문적으로 디렉터리이거나(split-path 참고) 경로에 확장자가 없으면 #f를 돌려줘요.

procedure

(find-relative-path base
                    path
                    [#:more-than-root? more-than-root?
                     #:more-than-same? more-than-same?
                     #:normalize-case? normalize-case?])
 → (or/c path-for-some-system? path-string?)
  base : (or/c path-string? path-for-some-system?)
  path : (or/c path-string?  path-for-some-system?)
  more-than-root? : any/c = #f
  more-than-same? : any/c = #t
  normalize-case? : any/c = #t

path와 같은 파일이나 디렉터리를 가리키는, base에 대한 상대 경로 이름을 찾아요. basepath 모두 simple-form-path의 의미로 단순화되어야 해요. pathbase와 공통인 서브경로를 전혀 공유하지 않으면 path를 돌려줘요.

more-than-root?가 참이고, basepath가 유닉스 루트만 공통으로 공유하며, basepath 둘 다 루트 경로만은 아니면, path를 돌려줘요.

pathbase와 같으면, more-than-same?#f일 때만 (build-path 'same)을 돌려줘요. 그 외에는, 그리고 기본적으로는, pathbase와 같을 때 path를 돌려줘요.

normalize-case?가 참(기본값)이면, 비교할 경로 요소 쌍은 먼저 normal-case-path로 변환돼요. 이는 Windows에서 경로 요소가 대소문자를 구분하지 않고 비교된다는 뜻이에요. normalize-case?#f면, 경로 요소와 경로 루트는 같은 대소문자를 가질 때만 일치해요.

결과는 보통 path?의 의미로 경로예요. 결과가 문자열인 것은 path가 문자열로 제공되고 결과로도 돌려줘질 때뿐이에요.

패키지 base의 버전 6.8.0.3에서 변경됨: 경로 요소를 비교를 위해 기본으로 대소문자 정규화하도록 하고, #:normalize-case? 인자를 추가했어요. 버전 6.90.0.21에서 변경됨: #:more-than-same? 인자를 추가했어요.

procedure

(normalize-path path [wrt]) → path?
  path : path-string?
  wrt : (and/c path-string? complete-path?) = (current-directory)

대부분의 목적에서 simple-form-path가 경로를 정규화하는 선호되는 방법이에요. 존재하지 않는 디렉터리 요소를 포함한 경로에도 동작하고, 불필요하게 소프트 링크를 확장하지 않기 때문이에요.

경로를 완전하게 만들고, 완전한 경로를 확장하고, 모든 소프트 링크를 해석(파일 시스템을 조사해야 함)함으로써 path의 완전한 버전을 돌려줘요. path가 상대 경로면 wrt가 기준 경로로 쓰여요.

normalize-path는 문자 대소문자를 정규화하지 않아요. 이런 이유와 다른 이유(예: 경로가 구문적으로 디렉터리인지 여부) 때문에, normalize-path의 결과는 두 경로가 같은 파일이나 디렉터리를 가리키는지 판별하는 비교에는 적합하지 않아요(즉 비교가 위음성 false negative를 낼 수 있어요).

normalize-path는 입력 경로가 존재하지 않는 디렉터리에 대한 임베디드 경로를 포함하거나, 소프트 링크의 무한 순환이 감지되면 오류를 신호해요.

예시를 볼게요:

> (equal? (current-directory) (normalize-path "."))
#t
procedure

(path-element? path) → boolean?
  path : any/c

path가 경로 요소이면 #t를 돌려줘요. 어떤 플랫폼에 대한 경로 값(즉 path-for-some-system?)이면서, 그것에 split-path를 적용하면 첫 결과로 'relative를, 두 번째 결과로 경로를 돌려줄 것 같은 값을 말해요. 그 외에는 결과가 #f예요.

procedure

(path-only path) → (or/c #f path-for-some-system?)
  path : (or/c path-string? path-for-some-system?)

path가 구문적으로 디렉터리가 아닌 경우, 마지막 경로 요소를 뺀 path를 돌려줘요. path가 단일한, 디렉터리가 아닌 경로 요소만 가지면 #f를 돌려줘요. path가 구문적으로 디렉터리면, path를 (문자열이었다면 경로로 바꿔서) 그대로 돌려줘요.

예시를 볼게요:

> (path-only (build-path "a" "b"))
#<path:a/>
> (path-only (build-path "a"))
#f
> (path-only (path->directory-path (build-path "a")))
#<path:a/>
> (path-only (build-path 'up 'up))
#<path:../..>
procedure

(simple-form-path path) → path?
  path : path-string?

(simplify-path (path->complete-path path))를 돌려줘요. 이는 결과가 up-이나 same- 디렉터리 지시자를 포함하지 않는 완전한 경로임을 보장해요.

procedure

(some-system-path->string path) → string?
  path : path-for-some-system?

경로 바이트의 UTF-8 인코딩을 사용해 path를 문자열로 변환해요.

다른 시스템을 위한 경로(그 경로 이름의 인코딩이 현재 로케일의 인코딩과 무관할 수 있는)를 다룰 때, 그리고 문자열로 시작해서 문자열로 끝날 때 이 함수를 쓰세요.

procedure

(string->some-system-path str kind) → path-for-some-system?
  str : string?
  kind : (or/c 'unix 'windows)

경로 바이트의 UTF-8 인코딩을 사용해 strkind 경로로 변환해요.

다른 시스템을 위한 경로를 다룰 때, 그리고 문자열로 시작해서 문자열로 끝날 때 이 함수를 쓰세요.

procedure

(shrink-path-wrt pth other-pths) → (or/c #f path?)
  pth : path?
  other-pths : (listof path?)

other-pths의 접미사와 공통인 것을 전혀 공유하지 않는 pth의 접미사를 돌려주거나, 불가능하면(예: other-pths가 비어 있거나 pth와 같은 요소만 가진 경로를 포함할 때) pth를 돌려줘요.

예시를 볼게요:

> (shrink-path-wrt (build-path "racket" "list.rkt")
                   (list (build-path "racket" "list.rkt")
                         (build-path "racket" "base.rkt")))
#<path:list.rkt>
> (shrink-path-wrt (build-path "racket" "list.rkt")
                   (list (build-path "racket" "list.rkt")
                         (build-path "racket" "private" "list.rkt")
                         (build-path "racket" "base.rkt")))
#<path:racket/list.rkt>

더 알아보기