Programming/TclTk
TCL UNIX에서 작업하기
Hunveloper
2022. 9. 6. 08:42
728x90
UNIX에서 작업하기
- 글의 기본은 UNIX를 기초로 하지만, DOS나 Macintosh 등에서도 TCL 해석기가 있기에 사용 가능
exec 명령으로 UNIX 프로그램 수행
- exec 명령은 TCL 스크립트에서 UNIX 명령을 수행
set d [exec date]
- 수행 결과는 표준 출력으로 출력된 결과
- 만약 수행한 프로그램이 표준 오류 출력으로 결과를 찍거나 상태 코드 값이 0이 아닐 경우는 에러
- exec 명령은 I/O redirection과 pipeline 구문을 완벽히 지원
- exec 명령에서 사용할 수 있는 여러 문법
- keepnewline : 결과값의 마지막에 있는 newline 문자를 없애지 않음
- | : pipeline
- |& : 표준 에러 출력으로도 파이프라인 수행
- < fileName : fileName 파일로부터 입력
- <@ fileId : fileId의 id를 가지는 I/O 스트림으로부터 입력
- << value : 주어진 값으로부터 입력
- > fileName : fileName 파일에 결과를 저장
- 2> fileName : fileName 파일에 표준 에러 출력 결과를 저장
- >& fileName : 표준 출력과 표준 에러 출력 결과를 모두 fileName 파일에 저장
- >>fileName : fileName 파일에 표준 출력 결과를 덧붙임 (append)
- 2>> fileName : fileName 파일에 표준 에러 출력 결과를 덧붙임
- >>& fileName : fileName 파일에 표준 출력과 표준 에러 출력 결과를 덧붙임
- >@ fileId : fileId id를 가지는 I/O 스트림에 표준 출력 결과를 저장
- 2>@ fileId : fileId id를 가지는 I/O 스트림에 표준 에러 출력 결과를 저장
- >&@ fileId : fileId id를 가지는 I/O 스트림에 표준 출력과 표준 에러 출력 결과를 저장
- & : 백그라운드로 수행. 결과값은 프로세스 ID.
- TCL 쉘 프로그램은 기본적으로 TCL 명령이 아닌 명령을 수행할 때 UNIX로 수행
- 이 기능을 종료하기 위해서 아래의 명령을 사용
set auto_noexec anything
파일 시스템
- file 명령은 파일의 상태를 알 수 있는 여러 명령을 제공
- 다음은 file 명령의 여러 형태를 나열한 것
- file atime name : 가장 최근에 파일에 접근한 시간을 10진수의 스트링으로 반환
- file dirname name : name 파일이 위치하는 디렉토리 이름을 반환
- file executable name : 실행 가능한 파일인 경우 1, 그렇지 않은 경우 0 반환
- file exists name : 파일이 존재하는 경우 1, 그렇지 않은 경우 0 반환
- file isdirectory name : name 파일이 디렉토리인 경우 1, 그렇지 않은 경우 0 반환
- file isfile name : name 파일이 디렉토리, 심볼릭 링크, 장치가 아닌 순수 파일인 경우 1, 그렇지 않으면 0 반환
- file mtime name : 파일의 최근 수정 시간을 반환
- file owned name : 현재 사용자가 파일의 소유자이면 1, 그렇지 않으면 0 반환
- file readable name : 파일의 내용 읽기가 허가되어 있으면 1, 그렇지 않으면 0을 반환
- file readlink name : 심볼릭 링크 name의 내용을 반환
- file root name : 확장자를 제외한 부분을 반환
- file extension name : 확장자 부분만을 반환
- file size name : 파일의 크기를 바이트 단위로 계산해 반환
- file stat name var : 파일의 상태를 var 배열에 삽입. var 배열에 정의되는 원소들은 atime, ctime, dev, gid, ino, mode, mtime, nlink, size, type, uid임
- file tail name : 파일의 경로를 제외한 파일 이름 부분만 반환
- file type name : 파일의 형태를 반환. 파일의 형태는 file, directorhy, characterSpecial, blockSpecial, fifo, link, socket 중의 하나
- file writable name : 파일 쓰기 허가가 되어 있으면 1, 그렇지 않으면 0을 반환
- 다음 예제는 두 파일의 수정 시간을 비교하기 위해 file mtime 명령을 사용
proc newer { file1 file2 } {
if ![file exists $file2] {
return 1
} else {
expr [file mtime $file] > [file mtime $file2]
}
}
- makedir 예제는 새로운 디렉토리를 생성할 필요가 있는지 검사하기 위해 file 명령을 사용
- makedir은 자신을 재귀적으로 호출
proc makedir { pathname } {
if {[file isdirectory $pathname]} {
return $pathname
} elseif {[file exists $pathname]} {
error "Non-directory $pathname already exists."
} else {
makedir [file dirname $pathname]
exec mkdir $pathname
return $$pathname
}
}
- 가장 일반적인 file의 옵션은 stat와 lstat, 세 번째 파라미터로 상태 정보를 받을 배열 변수를 가짐
- fileeq는 두 파일이 똑같은 file을 가리키는지를 찾음
proc fileeq { path 1 path2 } {
file stat $path1 stat1
file stat $path2 stat2
expr [$stat1(ino) == $stat2(ino) && \
$stat1(dev) == $stat2(dev)]
}
입출력 명령
- 입출력을 위한 명령
- open what ?access? ?permissions? : 파일이나 파이프라인에 대한 스트림 ID를 리턴
- puts ?-nonewline? ?stream? string : 스트링을 출력
- gets stream ?varname? : 한 줄을 읽음
- read stream ?numBytes? : numBytes 만큼의 바이트를 읽음
- read -nonewline stream : 스트림으로부터 모든 데이터를 읽고 마지막의 newline 제거
- tell stream : 현재 검색 중인 위치 리턴
- seek stream offset ?origin? : 검색 위치를 offset으로 설정. origin은 start, current, end 중 하나
- eof stream : end-of-file 상태를 질의
- flush stream : 스트림의 버퍼 쓰기
- close stream : I/O 스트림을 닫기
파일 열기
- open 명령은 입출력을 위해 파일을 연다
- open 명령의 리턴값은 I/O 스트림의 ID이다
- open의 결과를 저장해 두었다가 stdout이나 stdin, stderr을 사용한 부분에 대신 사용하면 됨
- open 명령의 기본적인 문법
open what ?access? ?permissions?
- what 파라미터는 파일이나 파이프라인의 이름
- access 파라미터는 짧은 문자의 나열로 쓸 수도 있고 POSIX 접근 flag 형태로 쓸 수도 있다.
- r : 존재하는 파일을 읽을 수 있도록 열기
- r+ : 존재하는 파일에 읽기와 쓰기를 함
- w : 존재하는 파일인 경우는 덮어 쓰고 존재하지 않으면 쓰기를 위해 생성함
- w+ : 존재하는 파일인 경우는 읽고 덮어 쓰고 존재하지 않으면 읽기와 쓰기를 위해 생성
- a : 존재하는 파일을 쓰기를 위해 열며 쓴 데이터는 뒤에 덧붙여 쓴다
- a+ : 존재하는 파일을 읽기와 쓰기를 위해 열며 쓴 데이터는 뒤에 덧붙여 쓴다
- access 파라미터를 POSIX 플래그 형태로 쓰는 경우
- RDONLY : 읽기전용
- WRONLY : 쓰기전용
- RDWR : 읽기와 쓰기
- APPEND : 파일에 덧붙임
- CREAT : 파일이 존재하지 않으면 새 파일을 생성
- EXCL : CREAT와 같이 쓸 때, 파일이 이미 존재하면 에러를 리턴
- NOCTTY: 터미널 장치가 컨트롤 터미널이 되는 것을 막음
- NONBLOCK: 파일을 여는 중에 블록 되지 않음
- TRUNC: 파일이 존재하면 끝을 자름
- access 파라미터는 기본적으로 read 값을 가짐
- permission은 파일 생성시 가지는 접근허가 비트, default 0666이며 chmod로 조정가능
- POSIX 형태의 파라미터를 사용해 파일을 여는 예
set filed [open /tmp/bar {RDWR CREAT}]
- 파일을 열 때에는 에러 발생 유무를 확인해야 함
- catch를 사용해 파일을 열 때에 발생한 오류를 확인
if [catch {open /tmp/data r} fileId] {
puts stderr "Cannot open /tmp/data : $fileId"
} else {
#read and process the file, then...
close $fileId
}
- catch는 에어가 발생시 1, 그렇지 않으면 0을 리턴
- catch의 두 번째 인자는 결과값을 받을 변수의 이름
- 파이프라인 문자인 ‘|’를 첫 번째 인자로 사용해 프로세스 파이프라인을 열 수 있음
- 다음 예제는 UNIX의 sort 프로그램을 사용해 password 파일을 sort후 split 명령을 사용해 결과라인을 리스트 원소로 변환
set input [open "\sort /etc/passwd" r]
set contents [split [read $input] \n]
close $input
- r+ 접근 모드를 사용하면 파일에 대한 읽기와 쓰기가 모두 가능하게 열 수 있음
- 파이프라인을 사용할 때에는 버퍼에 유의해야 함
- puts 명령이 수행된 후라도 버퍼에는 아직 데이터가 남아 있을 수 있음
- flush 명령을 사용하면 버퍼에 남아있는 데이터를 모두 출력
파일 읽기와 쓰기
- UNIX의 표준 I/O 스트림은 항상 열려 있음
- 기본적으로 열려 있는 스트림의 이름은 stdin, stdout, stderr
- 다른 스트림은 open 명령을 사용해 연다
- puts 명령은 출력 스트림에 스트링과 newline 문자를 출력
- -nonewline 옵션을 사용하면 마지막에 newline 문자를 출력하지 않음
puts -nonewline "Enter value : "
set answer [gets stdin]
- gets 명령은 한 줄의 입력을 받음
- gets 명령은 두 가지 형태로 사용가능
- gets의 첫 번째 형태는 위의 예제처럼 I/O 스트림으로부터 한 줄을 읽어 그 값을 반환
- gets는 마지막의 newline 문자를 없애 주며 파일의 끝에 도달한 경우는 빈 스트링을 반환
- 빈 줄과 파일의 끝을 구분하기 위해서는 eof 명령을 사용해야 함
- gets 명령에 두 번째 인자를 주게 되면 결과가 두 번째 인자에 쓰여진 변수에 들어가게 되며 리턴값은 스트링의 길이가 됨
- 파일의 끝에 다다른 경우는 -1을 반환
- 다음 예제는 파일의 처음부터 끝까지 읽는 루프의 예
while {[gets $stream line] >= -} {
#Process line
}
close $stream
- read 명령은 스트림에서 데이터를 블록 단위로 읽음
- read 명령도 두 형태로 사용 가능
- numBytes 파라미터를 주지 않으며 파일 전체의 내용을 반환
- -nonewline 옵션을 주면 마지막 newline 문자가 지워짐
- numBytes 파라미터를 주면 numBytes 만큼의 바이트를 읽음
- numBytes 파라미터와 -nonewline 옵션은 함께 사용할 수 없다
- 다음 예제는 read 명령을 사용해 파일의 내용을 읽는 예제
foreach line [split [read $stream] \n] {
#Process line
}
close $stream
- 일반적인 크기의 파일에서 gets를 사용하는 것보다 read를 사용하는 것이 더 빠름
- read는 파일 전체의 내용을 일고 split 명령이 read를 줄 단위로 나눔
- seek와 tell 명령을 사용하면 I/O 스트림의 랜덤한 위치를 접근가능
- 각 스트림은 seek offset이라고 불리는 스트림에서의 위치를 유지함
- 파일에서 읽거나 쓰면 seek offset에서 읽거나 쓴 바이트양이 증가
- tell 명령은 현재의 seek offset 값을 반환
- seek 명령은 seek offset 값을 설정
- close 명령은 I/O 스트림에 연결된 시스템 자원을 모두 해제하므로 중요한 명령
- 파일을 닫지 않으면 프로세스가 끝날 때 자동으로 닫힘
현재 디렉토리 cd와 pwd
- 모든 UNIX 프로세스는 파일을 찾을 때 기본 위치로 삼는 현재 디렉토리라는 것을 가지고 있음
- pwd 명령은 현재 디렉토리의 위치를 반환
- cd 명령은 현재 디렉토리를 변경
glob를 사용해 파일 이름 찾기
- glob 명령은 패턴을 이용해 파일 이름을 찾음
glob ?flags? pattern ?pattern?
- 패턴 파라미터의 문법은 string match 명령의 파라미터와 유사
-
- : 0개 이상의 문자와 대응
- ? : 하나의 문자와 대응
- [abc] : abc 문자 집합과 대응
- {a,b,c} : a,b,c 중의 하나와 대응
- 기타 다른 문자는 같은 문자와 대응
- nocomplain 옵션을 사용하면 일치하는 파일이 없는 경우 빈 스트링을 반환
- nocomplain 옵션을 사용하지 않으면 일치하는 파일이 없는 경우 에러를 발생
-
- FindFile 프로시져는 파일 시스템의 하위 디렉토리를 순차적으로 검색해 원하는 파일을 탐색
proc FindFile {startDir namePat} {
set pwd [pwd]
if [catch {cd $startDir} err] {
puts stderr $err
return
}
foreach match [glob -nocomplain -- $namePat] {
puts stdout $startDir/$match
}
foreach file [glob -nocomplain *] {
if [file isdirectory $file] {
FindFile $startDir/$file $namePat
}
}
cd $pwd
}
exit와 pid 명령
- exit 명령은 스크립트를 종료
- 스크립트를 수행하던 모든 UNIX 프로세스도 종료
- exit 명령은 정수 인자를 주면 그 인자가 프로세스의 종료 상태가 됨
- pid 명령은 현재 프로세스의 프로세스 ID를 반환
- 이 값은 수행할 때마다 변하기에 난수 발생기 seed의 값으로 활용 가능
환경 변수
- 환경 변수는 Unix 프로세스와 연결된 스트링 값을 가지는 변수들
- 프로세스의 환경 변수는 env 배열을 사용해 접근 가능
- 환경 변수의 이름은 배열의 인덱스가 되면 그 값이 환경 변수의 값과 같게 됨
- env 배열 값을 바꾸면 그 변경된 값은 환경 변수에도 반영됨
- 환경 변수는 자식 프로세스에게 상속
- 다음 프로그램은 환경 변수의 값을 화면에 출력
proc printenv { args } {
global env
set maxl 0
if {[llength $args] == 0} {
set args [lsort [array names env]]
}
foreach x $args {
if {[string length $x] > $maxl} {
set maxl [string length $x]
}
}
incr maxl 2
foreach x $args {
puts stdout [format "%*s = %s" $maxl $x $env($x)]
}
}
printenv USER SHELL TERM
728x90
728x90