glob — 패턴에 맞는 파일 이름 찾기
glob — 패턴에 맞는 파일 이름 찾기
쉘에서 *.tcl 같은 와일드카드로 파일 목록을 얻는 것처럼, Tcl 스크립트에서도 같은 방식으로 파일 이름을 찾고 싶을 때가 있어요. 그때 쓰는 명령어가 glob이에요.
본문
시그니처
glob ?switches? ?pattern ...?
glob은 csh 셸이나 bash 셸과 비슷하게 파일 이름 글러빙을 수행해요. pattern 인자 중 어느 하나라도 매칭되는 이름을 가진 파일들의 리스트를 반환해요. 리스트의 순서는 보장되지 않으니 정렬이 필요하면 lsort를 쓰세요.
옵션
glob 앞쪽 인자가 -로 시작하면 스위치로 취급돼요. 지원되는 스위치는 다음과 같아요.
-directory directory— 주어진 디렉토리에서 시작해 패턴과 매칭되는 파일을 찾아요. glob에 민감한 문자를 포함한 디렉토리 이름을 따로 이스케이프하지 않고도 검색할 수 있게 해줘요.-path와 함께 쓸 수 없어요.-join— 옵션 처리 후 남은 패턴 인자들을 디렉토리 구분자로 이어 붙인 하나의 패턴으로 취급해요.-nocomplain— 결과가 빈 목록이어도 오류 없이 반환되게 해요. 이 스위치가 없으면 결과가 비어 있을 때 오류가 나요.-path pathPrefix— 주어진pathPrefix로 시작하고 나머지 이름이 패턴과 매칭되는 파일을 찾아요. glob에 민감한 문자를 포함한 비슷한 이름의 파일들을 찾을 때 유용해요.-directory와 함께 쓸 수 없어요. 예를 들어$path와 루트 이름이 같지만 확장자가 다른 모든 파일을 찾으려면glob -path [file rootname $path] .*를 쓰면$path에 glob 민감 문자가 많아도 잘 동작해요.-tails— 어떤-directory나-path지정에서 마지막으로 이름 붙은 디렉토리 다음에 오는 부분만 반환해요.glob -tails -directory $dir *는set pwd [pwd]; cd $dir; glob *; cd $pwd와 같아요.-path지정에서는 반환된 이름이 마지막 경로 세그먼트를 포함해서,glob -tails -path [file rootname ~/foo.tex] .*는foo.aux foo.bib foo.tex같은 경로를 반환해요.-types typeList—typeList와 매칭되는 파일이나 디렉토리만 나열해요. 목록 항목은 두 가지 형태가 있어요.- 첫 번째 형태는 Unix
find의-type옵션과 같아요:b(블록 특수 파일),c(문자 특수 파일),d(디렉토리),f(일반 파일),l(심볼릭 링크),p(네임드 파이프),s(소켓). 여러 타입을 지정할 수 있고, 주어진 타입 중 하나라도 매칭되는 파일을 모두 반환해요. 심볼릭 링크는-types l을 주거나 링크의 대상이 요청 타입과 매칭될 때 모두 반환돼요(그래서 디렉토리로 가는 링크는-types d에서도 반환돼요). - 두 번째 형태는 주어진 타입이 전부 매칭되어야 해요: 파일 권한으로
r,w,x와 특별 권한 경우인readonly,hidden이에요. Macintosh에서는 macOS 타입·크리에이터도 지원해요(네 글자 항목은 macOS 타입, 예:TEXT).{macintosh type XXXX}나{macintosh creator XXXX}형태는 각각 타입·크리에이터와 매칭돼요. 인식 못 하는 타입이나 여러 macOS 타입·크리에이터를 지정하면 오류가 나요. - 두 형태는 섞을 수 있어요.
-types {d f r w}는 읽기 그리고 쓰기 권한이 둘 다 있는 일반 파일 또는 디렉토리를 모두 찾아요. 다음 둘은 동등해요:
단, 첫 번째는 끝의glob -type d * glob *//를 반환하지 않고 더 플랫폼 독립적이에요.
- 첫 번째 형태는 Unix
--— 스위치의 끝을 표시해요. 그다음 인자는-로 시작해도 패턴으로 취급돼요.
글러빙 패턴
pattern 인자에는 string match가 지원하는 것의 상위 집합인 다음 특수 문자가 들어갈 수 있어요.
| 패턴 | 의미 |
|---|---|
? |
임의의 한 문자 |
* |
0개 이상의 연속된 문자 |
[chars] |
chars 중 한 문자 (범위 a-b 가능) |
\x |
문자 x 자체 |
{a,b,...} |
a, b 등 하위 패턴 중 어느 하나 |
Unix에서는 csh처럼 파일 이름 시작 또는 / 바로 뒤의 .이 숨김을 뜻하므로 명시적으로({} 포함) 매칭해야 해요(-types hidden을 주면 예외). 다른 플랫폼에서는 .로 시작하는 파일을 일반 파일과 동일하게 다루되, 특별한 디렉토리 .과 ..만 명시적으로 매칭해야 해요(재귀 패턴이 디렉토리 계층을 위로도 올라가지 않게 하려는 것). 또 모든 / 문자는 명시적으로 매칭해야 해요.
패턴의 첫 문자가 ~이면 그 뒤에 오는 사용자 이름의 홈 디렉토리를 가리켜요. ~ 바로 뒤에 /가 오면 HOME 환경 변수의 값이 사용돼요.
glob은 csh 글러빙과 두 가지 점에서 달라요. 하나는 결과를 정렬하지 않는다는 점(lsort로 정렬), 다른 하나는 실제로 존재하는 파일만 이름을 반환한다는 점이에요(csh는 ?, *, []가 없는 패턴이면 존재 여부를 확인하지 않아요).
glob이 틸드 ~로 시작하는 상대 경로를 반환할 때(예: glob *이나 glob -tails), 반환 리스트는 틸드를 ./로 인용하지 않아요. 그래서 그 이름을 나중에 file join으로 쓸 때 사용자의 홈 디렉토리를 가리키는 절대 경로로 해석되지 않도록 주의해야 해요.
Windows 이식성 문제
Windows UNC 이름에서는 경로의 서버명·공유명 구성 요소에 ?, *, []를 쓸 수 없어요. Windows NT에서 ~username@domain 형태의 패턴은 지정된 NT 도메인 서버의 계정 정보를 가진 사용자의 홈 디렉토리를 가리키고, 그 외에는 로컬 컴퓨터에서 계정 정보를 가져와요.
백슬래시는 glob에 특별한 의미가 있으므로 Windows 스타일 경로 구분자를 포함한 패턴은 주의가 필요해요. C:\\foo\\*는 C:\foo\*로 해석되는데, 여기서 \f는 문자 f 하나와 매칭되고 \*는 문자 * 하나와 매칭돼(와일드카드가 아님)요. 해결책은 Unix 스타일 슬래시를 경로 구분자로 쓰는 거예요. Windows 스타일 경로는 file join $path나 file normalize $path로 Unix 스타일로 변환할 수 있어요.
예제
현재 디렉토리의 모든 Tcl 파일 찾기:
glob *.tcl
현재 디렉토리가 어디든 사용자 홈 디렉토리의 Tcl 파일 찾기:
glob -directory ~ *.tcl
현재 디렉토리의 모든 하위 디렉토리 찾기:
glob -type d *
이름에 a, b, 또는 연속 cde를 포함하는 모든 파일 찾기:
glob -type f *{a,b,cde}*