BashLecture1
From KBase
Contents |
[edit] Specifying Interpreter
Magic number 라는 것이 있는데, Windows 는 전통적으로 파일의 종류를 확장자로 구분하지만, unix 에서는 이 magic number 라는 것을 이용하여 파일을 구별하기도 한다. 예를 들어 ELF executable 은 파일의 맨 앞이 MZ 이고 GIF 파일은 GIF87 혹은 GIF89a 등이며, JPEG 파일은 파일의 앞부분에 JFIF 란 문자열이 들어 있다.
실행가능한 script 파일은 파일의 맨 앞 두글자가 #! 이고, 이후 newline 까지의 문자열이 해당 script 파일의 interpreter 로 사용된다. 따라서 bash script 는 #!/bin/bash 로 시작하며, perl script 는 #!/usr/bin/perl 로 시작하는 식이다. 내가 interpreter 를 만들었다면 #!/path/to/my/interpreter/mine 과 같이 지정해 줄 수도 있다.
bash 는 sh 를 기반으로 하고 있으므로 bash 만의 extension 을 사용했으면 #!/bin/bash 를 쓰면 되고, sh 와 호환 가능한 내용만을 썼으면 #!/bin/sh 를 쓰면 된다.
[edit] Command Sequence
command line 으로 입력할 명령어들을 나열하는 것만으로도 훌륭한 script 가 될 수 있다. 예를 들면 directory 를 바꾸고, 특정 파일을 삭제하고, 다시 원래 directory 로 돌아가서 특정 파일을 만드는 등의 역할을 수행하는 script 는 다음과 같다
#!/bin/sh cd subdir rm *.bak cd .. echo babo > babo.txt
[edit] Pipelines
두 개 process 사이의 file 을 연결해 주는 것을 pipeline 이라고 한다. shell 에서는 두 개의 프로그램을 실행시키고 그 중 하나의 stdout 과 나머지 하나의 stdin 을 연결하는 것을 뜻하게 된다. pipeline 은 vertical bar ( | ) 를 사용하여 다음과 같이 사용한다
/bin/ls | sed 's/^/file: /'
[edit] Comment
- 으로 시작하는 줄은 comment 로 처리된다. 라인의 중간부터 시작해도 된다. 맨 앞에 있는 #! 는 magic number 로 사용되므로 중간부터 시작하면 안된다.
[edit] Conditional Execution
Shell script 도 명색이 프로그램인데, 위와 같이 단순한 명령어의 나열에서 탈피하여 조건부로 실행되는 코드를 만들어 본다.
[edit] Exit status
process 가 종료할 때 보고하는 값이다. C 로 프로그램을 만들었다면 main() 이 리턴하는 값 (혹은 exit() 의 인자) 이다. 이 값을 이용하여 프로그램이 정상적으로 종료했는지, 혹은 어떤 비정상적인 이유로 종료했는지를 알 수 있다.
$ cat xx.c
#include <stdio.h>
int main(void)
{
return 123;
}
$ ./a.exe
$ echo $?
123
위에서 보는 것과 같이 main 이 리턴한 0 이 $? 에 출력되는 것을 볼 수가 있다.
전통적으로, exit status 가 0 이면 에러가 없는 것으로, 0 이 아니면 에러 코드인 것으로 간주된다. 파일을 복사하는 cp 의 예를 들어보자
$ cp xx.c kkk.c $ echo $? 0 $ cp notexist.c kk.c cp: cannot stat `notexist.c': No such file or directory $ echo $? 1
copy 를 잘 했을 경우는 $? 값이 0 이지만 없는 파일을 복사하려고 시도했을 때는 $? 값이 1 인 것을 볼 수 있다.
[edit] &&, ||
단순한 나열을 했을 때는 앞에 실행한 것이 실패했을 때도 다음 것을 시도하기 때문에 문제가 된다. 이럴 때는 다음과 같이 하나의 command 를 실행한 후 그 결과에 따라 다음 command 를 실행하도록 한다.
$ cp notexist.c kk.c && echo babo cp: cannot stat `notexist.c': No such file or directory $ cp xx.c kk.c && echo babo babo
위에서처럼 cp 가 성공했을 때만 echo 를 실행하게 된다.
=&&= 는 앞의 것이 성공했을 때 뒤의 것이 실행되며 || 는 앞의 것이 실패했을 때 뒤의 것이 실행된다.
[edit] if
=&&= 나 || 를 좀 더 구조적으로 쓰고 싶으면 if 를 쓴다
if test-commands; then consequent-commands; [elif more-test-commands; then more-consequents;] [else alternate-consequents;] fi
[edit] case
echo -n "Enter the name of an animal: " read ANIMAL echo -n "The $ANIMAL has " case $ANIMAL in horse | dog | cat) echo -n "four";; man | kangaroo ) echo -n "two";; *) echo -n "an unknown number of";; esac echo " legs."
* case 의 끝은 그 글자들을 뒤집은 esac 이다. 이것은 위에 나오는 if 도 그렇다. * pattern 은 ) 로 구분지으며, 명령어를 나열한 후 ;; 로 끝마친다.
[edit] select
select fname in *; do echo you picked $fname \($REPLY\) break; done
[edit] Loop
반복을 하고 싶을 때 사용한다
[edit] for / expression
$ for ((n=1;n<10;n++)); do echo $n; done 1 2 3 4 5 6 7 8 9
[edit] for / words
$ for fname in babo kakaka *.c; do echo $fname; done babo kakaka kk.c kkk.c xx.c yy.c zz.c
[edit] Quotes
single quote (') 에서는 interpolation (shell expansion) 이 일어나지 않는다. double quote (") 에서는 가능하다. back quote 는 실행 결과를 의미한다
$ a=`ls` $ b='a is: $a' $ c="a is: $a" $ echo $a C++Lect/ a.exe kk.c kkk.c scribble.GIF xx.c xx.exe yy.c yy.exe zz.c zz.exe $ echo $b; a is: $a $ echo $c a is: C++Lect/ a.exe kk.c kkk.c scribble.GIF xx.c xx.exe yy.c yy.exe zz.c zz.exe
[edit] Variables and Functions
[edit] Variable
=name=[value]= 와 같은 형태로 지정하고 앞에 $ 를 붙여서 읽는다
[edit] Function
syntax:
[edit] [ function ] name () compound-command [ redirections ]
[edit] Shell Parameters
[edit] Positional Parameters
$1, $2 와 같이 parameter 에 번호를 붙일 수 있다. $0 은 실행시킨 script 자신을 의미한다.
$ cat babo.sh #!/bin/sh echo 0: $0 echo 1: $1 echo 2: $2 $ ./babo.sh a b c 0: ./babo.sh 1: a 2: b
[edit] Special Parameters
$ cat ./babo.sh #!/bin/sh echo *: $* echo @: $@ echo \#: $# echo ?: $? echo -: $- echo \$: $$ echo !: $! echo 0: $0 echo _: $_ $ ./babo.sh a b c d *: a b c d @: a b c d #: 4 ?: 0 -: hB $: 3252 !: 0: ./babo.sh _: ./babo.sh
[edit] Shell Expansions
[edit] Brace
bash$ echo a{d,c,b}e
ade ace abe
[edit] Tilde
ls ~ ~scgyong
[edit] Parameter
$ a=babo
$ unset b
$ echo ${a}, ${b}
babo,
$ echo ${a:-kakaka}
babo
$ echo ${b:-kakaka}
kakaka
$ echo ${a:1}
abo
$ echo ${a:1:2}
ab
$ echo ${a#ba}
bo
[edit] Command Substitution (Back quote)
=$(command)= 혹은 `command`
[edit] Arithmetic
[edit] $((expression))
[edit] Filename
- , ?, [abc], [a-c]
[edit] Redirection
stdout (file descriptor 1)과 stderr (file descriptor 2) 를 모두 dirlist 로 redirect 하려면 다음과 같이 한다
ls > dirlist 2>&1
다음은 stdout 만을 dirlist 로 보내는데, stdout 이 dirlist 로 redirect 되기 전에 stderr 가 stdout 으로 duplicate 되기 때문이란다.
ls 2>&1 > dirlist

