file — 파일 이름·속성 다루기

file — 파일 이름·속성 다루기

파일을 복사하고, 삭제하고, 이름을 바꾸고, 존재 여부나 권한을 확인하고, 경로를 조작해야 할 때가 많아요. Tcl의 file 명령은 파일 이름과 속성에 대한 다양한 연산을 한곳에서 제공해요.

출처: Tcl 공식 문서 — file

본문

시그니처

file option name ?arg arg ...?

설명

이 명령은 파일 이름이나 속성에 대한 여러 연산을 제공해요. name은 파일 이름이고, 틸드로 시작하면 명령을 실행하기 전에 틸드 치환이 수행돼요(자세한 내용은 filename 매뉴얼 항목 참고). option은 파일 이름으로 무엇을 할지 나타내요. option의 고유한 축약은 받아들여져요. 유효한 옵션은 다음과 같아요.

주요 옵션

file atime name ?time?

파일 name이 마지막으로 접근된 시각을 주는 십진 문자열을 반환해요. time이 지정되면 파일에 설정할 접근 시각이에요. 시각은 표준 POSIX 방식으로 고정된 시작 시각(흔히 1970년 1월 1일)부터의 초로 측정돼요. 파일이 존재하지 않거나 접근 시각을 조회·설정할 수 없으면 에러가 나요. Windows에서 FAT 파일시스템은 접근 시각을 지원하지 않아요.

file attributes name

file attributes name ?option?

file attributes name ?option value option value...?

이 subcommand는 파일과 연관된 플랫폼별 값을 반환하거나 설정해요. 첫 형태는 플랫폼별 옵션과 그 값의 목록을 반환해요. 둘째 형태는 주어진 옵션의 값을 반환해요. 셋째 형태는 값 하나 이상을 설정해요. 값은 다음과 같아요.

Unix-group은 파일의 그룹 이름을 얻거나 설정해요. 명령에 그룹 id를 줄 수 있지만 그룹 이름을 반환해요. -owner는 파일 소유자의 사용자 이름을 얻거나 설정해요. 명령은 소유자 이름을 반환하지만, 설정할 때 수치 id를 넘길 수 있어요. -permissions는 기본적으로 8진 표기법으로 파일의 접근 권한을 가져오거나 설정해요. 이 옵션은 chmod 명령이 받아들이는 기호 표기법으로 권한을 설정하는 제한된 지원도 제공하는데, [ugo]?[[+-=][rwxst],[...]] 형식을 따라요. 여러 권한 명세를 쉼표로 구분해 줄 수 있어요. 예: u+s,go-rw는 파일 소유자의 setuid 비트를 설정하고 파일 그룹·기타 사용자의 읽기·쓰기 권한을 제거해요. rwxrwxrwx 형태의 ls-류 문자열도 받아들여지지만 항상 9자여야 해요. 예: rwxr-xr-t는 01755와 동등해요. 파일 플래그를 지원하는 Unix 버전에서 -readonly는 파일의 readonly 속성 값(chflags 명령의 user immutable 플래그, uchg)을 반환하거나 설정·해제해요.

Windows-archive는 파일의 archive 속성 값을 주거나 설정·해제해요. -hidden은 파일의 hidden 속성 값을 주거나 설정·해제해요. -longname은 각 경로 요소를 긴 버전으로 확장해요. 이 속성은 설정할 수 없어요. -readonly는 파일의 readonly 속성 값을 주거나 설정·해제해요. -shortname은 가능하면 각 경로 요소를 짧은(8.3) 버전의 이름으로 바꾼 문자열을 줘요. 짧은 이름으로 매핑할 수 없는 경로 요소에는 긴 이름이 유지돼요. 이 속성은 설정할 수 없어요. -system은 파일의 system 속성 값을 주거나 설정·해제해요.

macOS와 Darwin-creator는 파일의 Finder creator 타입을 주거나 설정해요. -hidden은 파일의 hidden 속성 값을 주거나 설정·해제해요. -readonly는 파일의 readonly 속성 값을 주거나 설정·해제해요. -rsrclength는 파일 리소스 포크의 길이를 주며, 이 속성은 0으로만 설정할 수 있어서(그 결과 리소스 포크가 파일에서 제거됨)요.

file channels ?pattern?

pattern을 지정하지 않으면 이 인터프리터에 등록된 모든 열린 채널의 이름 목록을 반환해요. pattern을 지정하면 그 패턴과 일치하는 이름만 반환해요. 일치는 string match와 같은 규칙을 써요.

file copy ?-force? ?--? source target

file copy ?-force? ?--? source ?source ...? targetDir

첫 형태는 파일·디렉터리 source의 복사본을 경로 target 아래에 만들어요. target이 기존 디렉터리면 둘째 형태가 쓰여요. 둘째 형태는 나열된 각 source 파일의 복사본을 targetDir 안에 만들어요. source로 디렉터리를 지정하면 그 디렉터리의 내용이 targetDir 안으로 재귀 복사돼요. -force 옵션을 지정하지 않으면 기존 파일은 덮어쓰지 않아요(-force일 때 Tcl은 복사를 진행하기 위해 필요하면 대상 파일·디렉터리의 권한을 조정하려고도 해요). 단일 파일시스템 안에서 복사할 때 file copy는 소프트 링크를 복사해요(즉 링크 자체가 복사되고, 그것이 가리키는 대상은 아님). -force를 지정해도 빈 디렉터리 아닌 것을 덮어쓰거나, 디렉터리를 파일로·파일을 디렉터리로 덮어쓰면 에러가 나요. 인자는 지정된 순서대로 처리되고, 첫 에러에서 멈춰요. --는 스위치의 끝을 나타내고, -- 다음 인자는 -로 시작해도 source로 취급돼요.

file delete ?-force? ?--? ?pathname ... ?

pathname 인자가 지정하는 파일·디렉터리를 제거해요. 빈 디렉터리 아닌 것은 -force 옵션을 지정할 때만 제거돼요. 심볼릭 링크에 대해 동작할 때는 링크 자체가 삭제되고 그것이 가리키는 대상은 아니에요. 존재하지 않는 파일을 삭제하려는 건 에러로 간주되지 않아요. 읽기 전용 파일을 삭제하려는 것은 -force 플래그를 지정하지 않아도 그 파일이 삭제되게 해요. 디렉터리에 -force 옵션을 지정하면 Tcl은 삭제를 진행하기 위해 필요하면 권한을 바꾸고 현재 디렉터리 "pwd"를 주어진 경로 밖으로 옮기려고 해요. 인자는 지정된 순서대로 처리되고 첫 에러에서 멈춰요. --는 스위치의 끝을 나타내고, -- 다음 인자는 -로 시작해도 pathname으로 취급돼요.

file dirname name

name에서 마지막 요소를 뺀 모든 경로 구성 요소로 이루어진 이름을 반환해요. name이 상대 파일 이름이고 경로 요소가 하나뿐이면 "."를 반환해요. name이 루트 디렉터리를 가리키면 루트 디렉터리를 반환해요. 예:

file dirname c:/

는 c:/를 반환해요. 틸드 치환은 명령을 완성하는 데 필요할 때만 수행돼요. 예:

file dirname ~/src/foo.c

는 ~/src를 반환하고,

file dirname ~

는 /home(또는 비슷한 것)을 반환해요.

file executable name

파일 name이 현재 사용자에 의해 실행 가능하면 1, 아니면 0을 반환해요. 실행 속성이 없는 Windows에서 이 명령은 모든 디렉터리와 exe, com, cmd, bat 확장자를 가진 파일을 실행 가능한 것으로 취급해요.

file exists name

파일 name이 존재하고 현재 사용자가 그것에 이르는 디렉터리에 대해 검색 권한을 가지면 1, 아니면 0을 반환해요.

file extension name

name의 마지막 요소에서 마지막 점을 포함해 그 뒤의 모든 문자를 반환해요. name의 마지막 요소에 점이 없으면 빈 문자열을 반환해요.

file isdirectory name

파일 name이 디렉터리면 1, 아니면 0을 반환해요.

file isfile name

파일 name이 일반 파일이면 1, 아니면 0을 반환해요.

file join name ?name ...?

파일 이름 하나 이상을 받아 현재 플랫폼의 올바른 경로 구분자를 써서 결합해요. 특정 name이 상대적이면 이전 파일 이름 인자에 이어 붙여져요. 아니면 이전 인자들은 버려지고 현재 인자부터 이어붙이기를 진행해요. 예:

file join a b /foo bar

는 /foo/bar를 반환해요. 어떤 이름이든 구분자를 포함할 수 있고, 결과는 항상 현재 플랫폼의 정규 형태(Unix·Windows 모두 /)라는 점에 주의하세요.

file link ?-linktype? linkName ?target?

인자가 하나뿐이면 그 인자는 linkName으로 가정되고, 이 명령은 linkName이 주는 링크의 값(즉 그것이 가리키는 파일의 이름)을 반환해요. linkName이 링크가 아니거나 그 값을 읽을 수 없으면(예: 일반 파일처럼 보이는 하드 링크의 경우) 에러를 반환해요.

인자가 둘이면 linkNametarget으로 가정돼요. linkName이 이미 존재하거나 target이 존재하지 않으면 에러를 반환해요. 아니면 Tcl은 target(반환값이기도 함)의 기존 파일시스템 객체를 가리키는 linkName이라는 새 링크를 만드는데, 링크 타입은 플랫폼별이에요(Unix에서는 심볼릭 링크가 기본). 이것은 사용자가 어떤 타입의 링크인지 상관하지 않고 크로스 플랫폼 방식으로 링크를 만들고 싶을 때 유용해요.

특정 타입의 링크만 만들고 싶다면(그리고 어떤 이유로든 불가능하면 에러를 신호하려면) 선택적 -linktype 인자를 줘야 해요. -linktype의 허용 값은 "-symbolic""-hard"예요.

Unix에서 심볼릭 링크는 상대 경로에 만들 수 있고, 그 경로는 실제 linkName의 위치에 상대적이어야 해요(cwd가 아니라). 하지만 상대 링크가 지원되지 않는 다른 모든 플랫폼에서는 링크를 만들기 전에 target 경로가 항상 절대·정규화 형태로 변환돼요(그래서 상대 경로는 cwd에 상대적으로 해석돼요). 게다가 "~user" 경로는 항상 절대 형태로 확장돼요. 링크를 전혀 지원하지 않거나 요청된 특정 타입을 지원하지 않는 파일시스템에서 링크를 만들면 에러 메시지가 반환돼요. 대부분의 Unix 플랫폼은 심볼릭·하드 링크 둘 다 지원해요(하드는 파일에만). Windows는 NTFS 드라이브에서 심볼릭 디렉터리 링크와 하드 파일 링크를 지원해요.

file lstat name varName

stat 옵션(아래 참고)과 같지만 stat 대신 lstat 커널 호출을 써요. 즉 name이 심볼릭 링크를 가리키면 varName에 반환되는 정보는 그것이 가리키는 파일이 아니라 링크에 대한 것이에요. 심볼릭 링크를 지원하지 않는 시스템에서는 이 옵션이 stat 옵션과 정확히 같게 동작해요.

file mkdir ?dir ...?

지정된 각 디렉터리를 만들어요. 각 경로 dir에 대해 이 명령은 존재하지 않는 부모 디렉터리와 dir 자신까지 모두 만들어요. 기존 디렉터리가 지정되면 아무 조치도 취하지 않고 에러도 반환하지 않아요. 기존 파일을 디렉터리로 덮어쓰려 하면 에러가 나요. 인자는 지정된 순서대로 처리되고 첫 에러에서 멈춰요.

file mtime name ?time?

파일 name이 마지막으로 수정된 시각을 주는 십진 문자열을 반환해요. time이 지정되면 파일에 설정할 수정 시각이에요(Unix touch와 동등). 시각은 표준 POSIX 방식으로 고정 시작 시각부터의 초로 측정돼요. 파일이 존재하지 않거나 수정 시각을 조회·설정할 수 없으면 에러가 나요.

file nativename name

파일의 플랫폼별 이름을 반환해요. 플랫폼별 호출(예: Windows에서 exec를 통한 하위 프로세스)에 넘겨야 하는 파일 이름이 필요할 때 유용해요(아래 EXAMPLES 참고).

file normalize name

파일시스템 객체(파일, 디렉터리, 링크 등)의 고유한 정규화된 경로 표현을 반환해요. 그것의 문자열 값은 고유 식별자로 쓸 수 있어요. 정규화된 경로는 모든 "../"·"./"가 제거된 절대 경로예요. 또한 네이티브 플랫폼의 "표준" 형식이에요. Unix에서 이는 경로에 이르는 세그먼트가 심볼릭 링크/별칭이 없어야 함을 뜻하고(마지막 경로 구성 요소는 심볼릭 링크일 수 있음), Windows에서는 긴 형태와 그 형태의 대소문자 의존성(고유하고 대소문자 의존적인 경로를 줌)을 원한다는 뜻이기도 해요. 경로의 마지막 링크에 관한 한 가지 예외는 필요해요. Tcl이나 사용자가 실제 심볼릭 링크 자체에 대해 동작(예: file delete, file rename, file copy는 심볼릭 링크에 대해 동작하도록 정의됨)하기를 원할 수 있기 때문이에요.

file owned name

파일 name이 현재 사용자가 소유하면 1, 아니면 0을 반환해요.

file pathtype name

absolute, relative, volumerelative 중 하나를 반환해요. name이 특정 볼륨의 특정 파일을 가리키면 경로 타입은 absolute예요. name이 현재 작업 디렉터리에 상대적인 파일을 가리키면 relative예요. name이 지정 볼륨의 현재 작업 디렉터리에 상대적인 파일이나 현재 작업 볼륨의 특정 파일을 가리키면 volumerelative예요.

file readable name

파일 name이 현재 사용자가 읽을 수 있으면 1, 아니면 0을 반환해요.

file readlink name

name이 주는 심볼릭 링크의 값(즉 그것이 가리키는 파일의 이름)을 반환해요. name이 심볼릭 링크가 아니거나 그 값을 읽을 수 없으면 에러를 반환해요. 심볼릭 링크를 지원하지 않는 시스템에서는 이 옵션이 정의되지 않아요.

file rename ?-force? ?--? source target

file rename ?-force? ?--? source ?source ...? targetDir

첫 형태는 경로 source가 지정하는 파일·디렉터리를 target으로 이름을 바꿔요. target 경로가 다른 디렉터리의 이름을 지정하면 파일을 이동해요. target이 기존 디렉터리면 둘째 형태가 쓰여요. 둘째 형태는 각 source 파일·디렉터리를 디렉터리 targetDir 안으로 이동해요. -force 옵션을 지정하지 않으면 기존 파일은 덮어쓰지 않아요. 단일 파일시스템 안에서 동작할 때 Tcl은 이것들이 가리키는 대상이 아니라 심볼릭 링크를 이름 변경해요. 빈 디렉터리 아닌 것을 덮어쓰거나, 디렉터리를 파일로·파일을 디렉터리로 덮어쓰면 모두 에러가 나요. 인자는 지정된 순서대로 처리되고 첫 에러에서 멈춰요. --는 스위치의 끝을 나타내고, -- 다음 인자는 -로 시작해도 source로 취급돼요.

file rootname name

name의 마지막 구성 요소에서 마지막 "." 문자를 포함하지 않고 그 전까지의 모든 문자를 반환해요. name의 마지막 구성 요소에 점이 없으면 name을 반환해요.

file separator ?name?

인자를 주지 않으면 이 플랫폼의 네이티브 파일에 대해 경로 세그먼트를 구분하는 데 쓰는 문자를 반환해요. 경로가 주어지면 그 경로를 담당하는 파일시스템이 자신의 구분 문자를 반환하도록 요청돼요. 어떤 파일시스템도 name을 받아들이지 않으면 에러가 나요.

file size name

파일 name의 크기를 바이트로 주는 십진 문자열을 반환해요. 파일이 존재하지 않거나 크기를 조회할 수 없으면 에러가 나요.

file split name

name의 경로 구성 요소를 요소로 하는 목록을 반환해요. 목록의 첫 요소는 name과 같은 경로 타입이에요. 다른 모든 요소는 상대적이에요. 경로 구분자는 요소가 명확히 상대적임을 보장하는 데 필요하지 않으면 버려져요. 예를 들어 Unix에서

file split /foo/~bar/baz

는 셋째 구성 요소를 쓰는 이후 명령이 틸드 치환을 시도하지 않도록 "/ foo ./~bar baz"를 반환해요.

file stat name varName

namestat 커널 호출을 호출하고, 커널 호출에서 반환된 정보를 담기 위해 변수 varName을 사용해요. VarName은 배열 변수로 취급되고, 다음 요소들이 설정돼요: atime, ctime, dev, gid, ino, mode, mtime, nlink, size, type, uid. type을 제외한 각 요소는 stat 반환 구조체의 해당 필드 값을 가진 십진 문자열이에요. 값의 의미에 대한 자세한 내용은 stat 매뉴얼 항목을 보세요. type 요소는 file type 명령이 반환하는 것과 같은 형태로 파일 타입을 줘요. 이 명령은 빈 문자열을 반환해요.

file system name

요소가 하나 또는 둘인 목록을 반환해요. 첫째는 파일에 쓸 파일시스템의 이름, 둘째(주어진다면)는 그 파일시스템 안 위치의 파일시스템별 성질·타입을 나타내는 임의 문자열이에요. 파일시스템이 한 타입의 파일만 지원하면 둘째 요소는 주어지지 않을 수 있어요. 예를 들어 네이티브 파일은 첫 요소 "native"와, 주어진다면 파일 시스템의 플랫폼별 타입 이름(예: Windows의 "NTFS", "FAT")인 둘째 요소를 가져요. 일반적인 가상 파일시스템은 "vfs"라는 확장 통해 가상 파일시스템으로 마운트된 원격 ftp 사이트의 파일을 나타내기 위해 "vfs ftp" 목록을 반환할 수 있어요. 파일이 어떤 파일시스템에도 속하지 않으면 에러가 나요.

file tail name

name의 마지막 파일시스템 구성 요소의 모든 문자를 반환해요. name의 끝의 디렉터리 구분자는 무시돼요. name에 구분자가 없으면 name을 반환해요. 그래서 file tail a/b, file tail a/b/, file tail b는 모두 b를 반환해요.

file tempfile ?nameVar? ?template?

임시 파일을 만들고 그 파일에 연 읽기-쓰기 채널을 반환해요. nameVar가 주어지면 임시 파일의 이름이 쓰일 변수를 지정해요. 없으면 Tcl은 더 이상 필요 없어지면 임시 파일이 삭제되도록 마련해요. template이 있으면 만들 때 쓸 파일 이름 템플릿의 부분(디렉터리, 기본 이름, 확장자 등)을 지정해요. 다만 일부 플랫폼은 이런 부분 중 일부·전부를 무시하고 내장 기본값을 쓸 수 있어요.

임시 파일은 네이티브 파일시스템에서만 만들어진다는 점에 주의하세요. 그래서 운영체제 네이티브 API와 파일 이름을 요구하는 외부 프로그램에 쓰여도 안심할 수 있어요.

file type name

파일 name의 타입을 주는 문자열을 반환하는데, file, directory, characterSpecial, blockSpecial, fifo, link, socket 중 하나예요.

file volumes

시스템에 마운트된 볼륨의 절대 경로를 적절한 Tcl 목록으로 반환해요. 루트 볼륨으로 마운트된 가상 파일시스템이 없으면 Unix에서 항상 "/"를 반환해요. 모든 파일시스템이 로컬로 마운트되기 때문이에요. Windows에서는 사용 가능한 로컬 드라이브 목록(예: "a:/ c:/")을 반환해요. 가상 파일시스템이 추가 볼륨을 마운트했으면 그것들이 반환된 목록에 있을 거예요.

file writable name

파일 name이 현재 사용자가 쓸 수 있으면 1, 아니면 0을 반환해요.

이식성 이슈

Unix — 이 명령들은 항상 실효(effective)가 아닌 실제(real) 사용자·그룹 식별자로 동작해요.

Windowsfile owned subcommand는 다른 사용자를 가장(impersonate)하고 있을 수도 있는 스레드 토큰이 아니라 프로세스 토큰의 사용자 식별자(SID)를 써요.

예제

주어진 디렉터리에서 현재 디렉터리에 같은 이름의 오브젝트 파일을 가진 C 파일을 찾는 프로시저예요:

proc findMatchingCFiles {dir} {
 set files {}
 switch $::tcl_platform(platform) {
 windows {
 set ext .obj
 }
 unix {
 set ext .o
 }
 }
 foreach file [glob -nocomplain -directory $dir *.c] {
 set objectFile [file tail [file rootname $file]]$ext
 if {[file exists $objectFile]} {
 lappend files $file
 }
 }
 return $files
}

파일 이름을 바꾸고 옛 위치에서 새 위치를 가리키는 심볼릭 링크를 남겨요:

set oldName foobar.txt
set newName foo/bar.txt
# Make sure that where we're going to move to exists...
if {![file isdirectory [file dirname $newName]]} {
 file mkdir [file dirname $newName]
}
file rename $oldName $newName
file link -symbolic $oldName $newName

Windows에서 파일을 쉽게 "시작"할 수 있지만(Explorer 인터페이스에서 더블클릭하는 것과 동등), 운영체제에 넘기는 이름은 네이티브 형식이어야 해요:

exec {*}[auto_execok start] {} [file nativename ~/example.txt]

더 알아보기

  • filename, open, close, eof, gets, tell, seek, fblocked, flush
  • 키워드: attributes, copy files, delete files, directory, file, move files, name, rename files, stat, user