제8장 C 쉘 창병모 2012.09
8.1 C 쉘의 특징
C 쉘(C shell) C 쉘 쉘의 핵심 기능들 모두 포함 히스토리, 별명, 작업 제어 등의 새로운 기능 히스토리, 별명, 작업 제어 등의 새로운 기능 C 언어와 유사한 강력한 프로 그램(스크립트) 작성 기능 유닉스, 리눅스뿐만 아니라 맥 OS X 등에서도 제공 C 쉘의 개선된 버전 tcsh
C 쉘 시작 과정 단계 쉘 타입 액션 1 모든 쉘 ~/.cshrc 2 로그인 쉘 /.login 3 ~/.login
시작 파일 예 .login .cshrc echo Hello, $USER ! echo Welcome to UNIX echo -n "Today is "; date set term = vt100 set path=(. /bin /usr/bin /usr/local/bin) set history = 40 set prompt = '\! % ' stty erase ^H .cshrc alias h history alias dir ls -aF alias ll ls -l alias m more alias x chmod +x
8.2 C 쉘의 추가 기능
별명 alias 명령어 현재까지 정의된 별명들을 확인 이미 정의된 별명 해제 스트링이 나타내는 기존 명령에 대해 새로운 단어를 별명으로 정의 $ alias 단어 스트링 $ alias dir ls -aF $ dir $ alias h history $ alias list ls –l 현재까지 정의된 별명들을 확인 $ alias # 별명 리스트 dir ls -aF h history list ls –l 이미 정의된 별명 해제 $ unalias 단어
히스토리 입력된 명령들을 기억하는 기능 기억할 히스토리의 크기 로그아웃 후에도 히스토리 가 저장되도록 설정 입력된 명령들을 기억하는 기능 $ history [-rh] [번호] 기억할 히스토리의 크기 % set history = 40 로그아웃 후에도 히스토리 가 저장되도록 설정 % set savehist = 32 $ history 1 ls 2 who 3 env 4 vi test.sh 5 chmod +x test.sh 6 test.sh 7 ls 8 date 9 history ...
재실행 예 % !! # 바로 전 명령 재실행 % !20 # 20번 이벤트 재실행 % !! # 바로 전 명령 재실행 % !20 # 20번 이벤트 재실행 % !gcc # gcc로 시작하는 최근 명령 재실행 % !?test.c # test.c를 포함하는 최근 명령 재실행 % set prompt = '\! % ' 형태 의미 !! 바로 전 명령 재실행 !n 이벤트 번호가 n인 명령 재실행 !시작스트링 시작스트링으로 시작하는 최후 명령 재실행 !?서브스트링 서브스트링을 포함하는 최후 명령 재실행
출력 재지정 표준출력 재지정 표준출력과 표준오류까지도 재지정 표준출력 및 표준오류를 분리하여 저장 % 명령어 > 파일 % gcc a.c > errors 표준출력과 표준오류까지도 재지정 % 명령어 >& 파일 % gcc a.c >& errors 표준출력 및 표준오류를 분리하여 저장 % (명령어 > 파일1) >& 파일2 % (gcc a.c > out) >& errors
파이프 명령어1의 표준출력이 파이프를 통해 명령어2의 표준입력 표준출력 및 표준오류를 파이프 보내기 % 명령어1 | 명령어2 % gcc a.c | wc 표준출력 및 표준오류를 파이프 보내기 % 명령어1 |& 명령어2 % gcc a.c |& wc 표준출력 및 표준오류를 분리 % (명령어1 > 파일) |& 명령어2 % (gcc a.c > out) |& wc
7.3 변수
단순 변수(simple variable) 하나의 값(문자열)만을 저장할 수 있는 변수 % set 변수이름 = 단어 % set city = seoul 변수의 값 사용 % echo $city seoul 변수에 어느 때나 필요하면 다른 값을 대입 % set city = pusan 변수만 생성하고 빈 스트링으로 자동으로 초기화 % set 변수이름 한 번에 여러 개의 변수를 생성 % set country=korea color city=seoul
단순 변수 한글 스트링을 값으로 사용 따옴표를 이용하면 여러 단어로 구성된 스트링을 저장 % set country=대한민국 city=서울 % echo $country $city 대한민국 서울 따옴표를 이용하면 여러 단어로 구성된 스트링을 저장 % set address="서울시 용산구 청파동"
리스트 변수(list variable) 한 변수에 여러 개의 값(문자열)을 저장할 수 있는 변수 리스트 변수 사용 % set 변수이름 = ( 단어리스트 ) % set cities = (서울 부산 목포) 리스트 변수 사용 리스트 사용 의미 $name[i] ${name[i]} 리스트 변수 name의 i번째 원소 $#name ${#name} 리스트 변수 name의 원소의 수
리스트 변수 사용 예 리스트 변수 사용 리스트의 크기 리스트 변수에 새로운 도시 추가 % echo $cities 서울 부산 목포 % echo $cities[1] 서울 % echo $cities[2-3] # 부분범위 사용 가능 부산 목포 리스트의 크기 % echo $#cities[*] # 리스트 크기 3 $ echo $cities[4] 리스트 변수에 새로운 도시 추가 % set cities=($cities 제주) % echo $cities[4] 제주
8.4 지역변수와 환경변수
환경변수와 지역변수 쉘 변수 환경변수와 지역변수 두 종류로 나눌 수 있다. 환경 변수는 값이 자식 프로세스에게 상속되며 지역변수는 그렇 지 않다.
환경변수와 지역변수 예 지역 변수 환경 변수 % set 변수이름 = 단어 % set city = seoul % setenv 변수이름 단어 % setenv LANG ko
사전 정의 지역 변수(predefined local variable) 이름 값 $< 표준입력으로부터 읽은 한 줄 $argv 명령줄 인수 $argv[1] = $1 $cwd 현재 작업 디렉터리 $history 히스토리 크기 $home 홈 디렉터리 $$, $n, $* 프로세스 번호, 명령줄 인수 $prompt 쉘 프롬프트 $shell 로그인 쉘의 경로명 $path 명령어를 탐색할 경로 리스트 $term 사용하는 터미널 타입 % set input = $< hello C shell ! % echo $input
사전 정의 지역변수: 예 #!/bin/csh # local.csh echo 이 스크립트의 이름: $argv[0] echo 홈 디렉터리: $home echo 현재 작업 디렉터리: $cwd echo 로그인 쉘: $shell % local.csh hello csh 이 스크립트의 이름: 첫 번째 명령줄 인수: hello 명령줄 인수 개수: 2 홈 디렉터리: /user/faculty/chang 현재 작업 디렉터리: /user/faculty/chang/unix/csh 로그인 쉘: /bin/csh
사전 정의 환경변수(predefined environment variable) % setenv # 환경 변수 리스트 이름 값 $HOME $home $USER $user $TERM $term $PATH $path $PWD $cwd $TERMCAP 사용하는 터미널의 특성 $LD_LIBRARY_PATH ld(linkage editor)가 사용하는 라이브러리 경로 리스트 $LOGNAME 쉘 소유자의 로그인 이름
8.5 C 쉘 스크립트
Bash 스크립트 작성 및 실행 과정 (1) 에디터를 사용하여 C 쉘 스크립트 파일을 작성한다. #!/bin/csh # state.csh echo -n 현재 시간: date echo 현재 사용자: who echo 시스템 현재 상황: uptime (2) chmod를 이용하여 실행 모드로 변경한다. % chmod +x state.csh (3) 스크립트 이름을 타입핑하여 실행한다. % state.csh
if 문 if 문 예 if-then 문 if (수식) 명령어 set input = $< if ( $input == "yes") echo hello world ! if-then 문 if (수식) then 명령어리스트 endif #!/bin/csh # 사용법: wc.csh 파일 # 명령줄 인수 개수를 확인하고 wc 명령 어를 실행한다. if ($#argv != 1) then echo 사용법: $0 파일 exit 1 endif set file = $argv[1] wc $file % wc.csh 사용법: wc.csh 파일 % wc.csh cs1.txt 38 318 2088 cs1.txt
if-then-else if-then-else 구문 if (수식) then 명령어리스트 else endif #!/bin/csh # 사용법: count.bash [디렉터리] # 대상 디렉터리 내의 파일과 서브디렉터리 개수를 프린트한다. if ($#argv == 0) then set dir = "." else set dir = $argv[1] endif echo -n $dir 내의 파일과 서브디렉터리 개 수: ls $dir | wc –l % count.csh . 내의 파일과 서브디렉터리 개수: 17
8.6 수식
수식 C 쉘의 수식 문자열 비교 연산 파일 관련 연산 산술 연산
문자열 비교 연산자 #!/bin/csh # 사용법: reply.csh # 계속 여부를 입력받아 프린트한다. echo -n "계속 하시겠습니까 ?" set reply = $< if ($reply == "예") then echo 예 else if ($reply =~ 아*) then echo 아니오 endif % reply.csh 계속 하시겠습니까 ?아니 아니오 문자열 비교 연산자 의미 == 두 스트링이 같으면 참 아니면 거짓 != 두 스트링이 다르면 참 아니면 거짓 =~ ==과 같으며 대표문자 사용할 수 있다. !~ !=과 같으며 대표문자 사용할 수 있다.
파일 관련 연산 파일 관련 연산자 의미 -e 파일이름 해당 파일이 존재하면 참 -r 파일이름 사용자가 해당 파일을 읽을 수 있으면 참 -w 파일이름 사용자가 해당 파일을 쓸 수 있으면 참 -x 파일이름 사용자가 해당 파일을 실행할 수 있으면 참 -o 파일이름 사용자가 해당 파일의 소유자이면 참 -z 파일이름 해당 파일의 크기가 0이면 참 -f 파일이름 해당 파일이 일반 파일이면 참 -d 파일이름 해당 파일이 디렉터리이면 참
파일 관련 연산: 예 if (-e $file) then # $file이 존재하면 wc $file else # $file이 존재하지 않으면 echo "오류 ! 파일 없음" endif if (-d $dir) then echo -n $dir 내의 파일과 서브디렉 터리 개수: ls $dir | wc -l else echo $dir\: 디렉터리 아님 endif
부울 연산자 조건식에 부울 연산자 사용 ! 부정(negation) && 논리곱(logical and) || 논리합(logical or) # $file이 일반파일이고 쓸 수 있으면 if (-f $file && -w $file ) then uptime > $file endif if ( ! -e $file ) then # $file이 존재하지 않으면 echo $file : 파일 없음 endif if ( ! -d $file ) then # $dir이 디렉터리가 아니면 echo $file : 디렉터리 아님
산술 연산 산술 연산 % @ i = 20 / 5 * 2 % echo $i 2 @ 명령어를 이용한 산술연산 % set a = 2 * 3 @ 명령어를 이용한 산술연산 @ 변수이름 = 수식 % @ a = 2 * 3 % echo $a 6 % @ a = $a + 2 8 % @ a *= 10 % @ b++ % @ i = 20 / 5 * 2 % echo $i 2 % @ i = 9 - 4 + 2 3
산술 연산자 산술 연산자 의미 - 단일항 음수 ! 논리 부정 * / % 곱셈, 나눗셈, 나머지 + - 덧셈, 뺄셈 << >> 비트 좌이동, 비트 우이동 <= >= < > 관계 연산 == != 동등, 비동등 || && 논리합, 논리곱 & ^ | 비트 and, 비트 xor, 비트 or
8.7 제어구조
C 쉘 제어구조 조건 if 스위치 switch 반복 for, while
조건문 If-then 문 중첩 조건문 if (수식) 명령어 if (수식) then 명령어리스트 if (수식) then endif else 중첩 조건문 if (수식) then 명령어리스트 else if (수식) then else endif
중첩 조건문: 예 #!/bin/csh # 사용법: score1.csh # 점수에 따라 학점을 결정하여 프린 트한다. echo -n '점수 입력: ' set score = $< if ($score >= 90) then echo A else if ($score >= 80) then echo B else if ($score >= 70) then echo C else echo 노력 요함 endif % score1.csh 점수 입력: 85 B
스위치 switch (스트링) case 패턴1: 명령어리스트 breaksw case 패턴2: ... default: endsw #!/bin/csh # 사용법: score2.csh # 점수에 따라 학점을 결정하여 프린트 echo -n '점수 입력: ' set score = $< @ grade = $score / 10 switch ($grade) case "10" : case "9": echo A breaksw case "8": echo B case "7": echo C default: echo 노력 요함 endsw switch (스트링) case 패턴1: 명령어리스트 breaksw case 패턴2: ... default: endsw
반복문: for for 구문 리스트의 각 값에 대해서 명 령어들을 반복 foreach 변수이름 (단어리스트) 명령어리스트 end #!/bin/csh # 사용법: invite.csh # 저녁 초대 메일을 보낸다. set list = (lee kim choi) foreach $person ($list) echo “초대의 글 : 오늘 저녁 식사 모 임에 초대합니다.”| \ mail "${person}@gmail.com" end
모든 명령줄 인수 처리 모든 명령줄 인수 처리 foreach file ($argv) ... end 실행 결과 % filesize1.csh cs1.txt cs2.txt 파일 이름 크기(바이트) cs1.txt 2088 cs2.txt 1247 #!/bin/csh # 사용법: filesize1.csh 파일* # 대상 파일들의 이름과 크기를 프린트 if ($#argv == 0) then echo 사용법: $0 파일* exit 1 endif echo "파일 이름 크기(바이트)" foreach file ($argv) if (-f $file) then set fileinfo = `ls -l $file` set size = $fileinfo[5] echo "$file $size" end
반복문: while while 문 조건에 따라 명령어들을 반 복적으로 실행 while (수식) 명령어리스트 end #!/bin/csh # 사용법: power.csh # 2의 1승부터 10승까지 프린트한다. set i = 2 set j = 1 while ( $j <= 10 ) echo '2 ^' $j = $i @ i *= 2 @ j++ end $ power.csh 2 ^ 1 = 2 2 ^ 2 = 4 … 2 ^ 10 = 1024
menu.csh #!/bin/csh # 사용법: menu.csh # 메뉴에 따라 해당 명령어를 실행 echo 명령어 메뉴 set stop = 0 while ($stop == 0) cat << MENU d : 날짜 시간 l : 현재 디렉터리 내용 w : 사용자 보기 q : 끝냄 MENU echo -n '? ' set reply = $< switch ($reply) case "d" : date breaksw case "l": ls case "w": who case "q": set stop = 1 default: echo 잘못된 선택 endsw end
menu.csh $ menu.csh 명령어 메뉴 d : 날짜 시간 l : 현재 디렉터리 내용 w : 사용자 보기 q : 끝냄 ? d 2012년 2월 23일 목요일 오후 07시 33분 27초 ? q
8.8 고급 기능
디버깅 $ csh -vx 스트립트 [명령줄 인수] % csh -v menu.csh echo 명령어 메뉴 명령어 메뉴 set stop = 0 while ( $stop == 0 ) cat << MENU d : 날짜 시간 l : 현재 디렉터리 내용 w : 사용자 보기 q : 끝냄 echo -n '? ' ? set reply = $< d switch ( $reply ) date 2011년 12월 9일 금요일 오후 04시 14분 18초 breaksw end echo -n '? ' ? set reply = $< q set stop = 1 while ( $stop == 0 )
디버깅 % csh -x menu.csh echo 명령어 메뉴 명령어 메뉴 set stop = 0 while ( 0 == 0 ) cat d : 날짜 시간 l : 현재 디렉터리 내용 w : 사용자 보기 q : 끝냄 echo -n ? ? d set reply = d switch ( d ) date 2012년 2월 25일 토요일 오후 06시 03분 37초 breaksw end while ( 0 == 0 ) cat d : 날짜 시간 l : 현재 디렉터리 내용 w : 사용자 보기 q : 끝냄 echo -n ? ? q set reply = q switch ( q ) set stop = 1 while ( 1 == 0 )
shift shift 명령어 명령줄 인수[리스트 변수]의 원소들을 하나씩 왼쪽으로 이동 shift [리스트변수] #!/bin/csh # 사용법: filesize2.csh 파일* # 대상 파일들의 이름과 크기를 프린트 if ($#argv == 0) then echo 사용법: $0 파일* exit 1 endif echo "파일 이름 크기(바이트)" while ($#argv) set file = $argv[1] if (-f $file) then set fileinfo = `ls -l $file` set size = $fileinfo[5] echo "$file $size" endif shift end
디렉터리 내의 모든 파일 처리 디렉터리 내의 모든 파일 처리 해당 디렉터리로 이동 for 문과 대표 문자 *를 사용 대표 문자 *는 현재 디렉터리 내의 모든 파일 이름들로 대치 cd $dir foreach file (*) ... end
디렉터리 내의 모든 파일 처리: 예 #!/bin/csh #대상 디렉터리 내의 파일, 서브디렉터리, 기타 개수를 세서 프린트한다. #사용법: count.csh [디렉터리] if ($#argv == 0) then set dir = "." else set dir = $argv[1] endif if (! -d $dir) then echo $0\: $dir 디렉터리 아님 exit 1 @ fcount = 0 @ dcount = 0 @ others = 0
디렉터리 내의 모든 파일 처리: 예 echo $dir\: cd $dir foreach file (*) if (-f $file) then @ fcount++ else if (-d $file) then @ dcount++ else @ others++ endif end echo 파일: $fcount 디렉터리: $dcount 기타: $others
리커전(recursion) 스크립트도 자기 자신을 호출 가능 스크립트도 자기 자신을 호출 가능 어떤 디렉터리의 모든 하위 디 렉터리에 대해 동일한 작업을 수행할 때 매우 유용함 #!/bin/csh # 사용법 rhead.csh [디렉터리] # 대상 디렉터리와 모든 하위 디렉터리 내에 있는 파일들의 헤더를 프린트 cd $argv[1] foreach file (*) if (-f $file) then echo "========== $file ===========" head $file endif if (-d $file) then /home/… /rhead.csh $file end
터미널에서 실행 터미널에서 while 혹은 for 문도 실행 % foreach f (*) ? if (-d $f) echo $f ? end % set i = 2 % set j = 1 % while ($j <= 10) ? echo '2 **' $j = $i ? @ i *= 2 ? @ j++ ? end 2 ^ 1 = 2 2 ^ 2 = 4 … 2 ^ 10 = 1024
핵심 개념 단순 변수는 하나의 값(문자열)을 리스트 변수는 여러 개의 값(문 자열)을 저장할 수 있다. 쉘 변수는 크게 환경변수와 지역변수 두 종류로 나눌 수 있다. 환 경 변수는 값이 자식 프로세스에게 상속되며 지역변수는 그렇지 않다. C 쉘은 조건, 스위치, 반복 등을 위한 제어구조로 if, switch, foreach, while 등의 문장을 제공한다. C 쉘의 수식은 문자열 비교 연산, 파일 관련 연산, 산술 연산 등 을 사용할 수 있다.