<In Story>

Bash Shell Script 기초 배우기 // [Linux] [Script] [Programming] 본문

Programming/Script

Bash Shell Script 기초 배우기 // [Linux] [Script] [Programming]

<In Story, Hi story, History> 2015. 5. 4. 18:55

http://coffeenix.net/doc/shell/introbashscript.htm


원문http://www.linuxnewbie.org/nhf/intel/programming/introbashscript.html

날짜: ?

저자: X_console shellscope@yahoo.com

제목: BASH  스크립팅 입문버전 1.2

 

리눅스에서 쓸 수 있는 모든 쉘들처럼, BASH(Bourne Again Shell)은 뛰어난 명령 라인 쉘이면서, 그 자체로도 하나의 스크립팅 언어이다. 당신은 쉘 스크립팅을 이용해서 쉘이 가진 능력을 충분히 활용할 수 있으며, 쉘 스크립팅이 아니었으면  수많은 명령을 필요로 했을 많은 일들을 자동적으로 처리할 수도 있다. 당신의 리눅스 박스에 놓여 있는 많은 프로그램들은 쉘 스크립트들이다. 만일 쉘 스크립트가 어떻게 작동하는지 배우고 싶거나 당신이 가지고 있는 쉘 스크립트를 수정하고 싶다면, bash 문법을 이해하는 것은 필수적이다. 게다가, bash 언어를 이해하면 정확히 당신이 원하는 방식으로 일을 하는 당신 자신의 프로그램을 작성할 수 있다.  
 

프로그래밍 또는 스크립팅? 
프로그래밍을 처음 하는 사람들은 대개 프로그래밍 언어와 스크립팅 언어 사이의 차이를 혼동한다프로그래밍 언어는 일반적으로 스크립팅 언어에 비해 보다 강력하고 보다 빠르다프로그래밍 언어의 예로는 C, C++, Java 있다프로그래밍 언어는 대개 소스 코드(최종 프로그램이 어떻게 실행될 것인가에 대한 지시문을 담고 있는 텍스트 파일)에서 시작해서 컴파일 과정을 통해 실행 가능 파일로 만들어 진다(built). 이렇게 해서 만들어진 실행 가능 파일은 다른 운영 체제로 쉽게 이식되어지지 않는다예를 들어당신이 리눅스에서 C 프로그램을 작성했다면, Windows 98시스템에서는  프로그램을 실행할  없을 것이다프로그램을 실행하기 위해서는, Windows 98 시스템 하에서 소스 코드를 다시 컴파일해야만 한다스크립팅 언어 역시 소스 코드에서 시작을 하지만실행 가능 파일로 만들기 위한 컴파일 과정이 없다대신번역기(interpreter) 소스파일에서 지시문을 읽고  지시문을 실행시킨다불행히도번역기가  지시문을 하나 하나 읽어야만 하기 때문에일반적으로 번역기를 통해 실행되는 프로그램은 컴파일된 프로그램보다 느리다스크립팅 언어의가장  장점은 소스 파일을 어떤 운영 체제에나 쉽게 이식할  있으며 바로  자리에서 번역기를 통해 실행할  있다는 것이다이런 점은 작은 프로그램에서는 장점으로 여겨질  있지만 규모의 어플리케이션을 작성할 것을 계획하고 있다면 프로그래밍 언어를 사용하는 편이 알맞다스크립팅 언어의 예로는 Perl, Lisp, Tcl 있다.

무엇을 알아야 하는가?
당신 자신의  스크립트를 작성하기 위해서는 매일 사용하는 기본적인 리눅스 명령어를 알아야 한다예를 들면어떻게 파일을 복사이동하고 새로운 파일을 만드는지 하는 것들을 알아야만 한다반드시 알아두어야    가지는 텍스트 편집기를 쓰는 방법이다리눅스의 대표적인  가지 텍스트 편집기는 vi, emacs, pico이다만일 vi emacs 사용하는데 익숙하지 않다면, pico 사용하기 쉬운 다른 텍스트 편집기를 이용하라.

주의!!!
루트 사용자인 상태에서는 절대로 스크립팅을 연습하지 않도록 하라어떤 일이 일어날  모른다만일 당신이 코딩을 하는 도중 우연히 실수를 해서 시스템을 망쳤다 해도 나는 책임질  없다루트 권한이 없는 일반 사용자 계정을 사용하라당신은 스크립팅 연습을 하기 위한 새로운 사용자를 만들기를 원할 지도 모른다 경우일어날  있는 가장 나쁜 일은 새로 만든 사용자 디렉토리가 없어지는 것에 불과하다.

첫번째 BASH 프로그램
우리의 첫번째 프로그램은 고전적인 "Hello World" 프로그램이  것이다만일 당신이 이전에 프로그램을 해본 경험이 있다면지금까지 수많은 "Hello World" 프로그램을 봐왔을 것이다하지만이것은 전통이고누가그 전통을 바꾸겠는가 "Hello World" 프로그램은 단순히 "Hello World" 문구를 화면에 프린트하는 것이다그럼 우선 텍스트 편집기를 시작해서 안에 다음의 내용을 입력하라:

#!/bin/bash
echo "Hello World"

첫번째 라인은 리눅스에게  스크립트를 실행하기 위해서 bash 번역기를 사용하라고 알려준다 경우에는, bash /bin 디렉토리에 있다만일 bash 시스템의 다른 디렉토리에 있다면 위치를 첫번째 라인에 써주어라스크립트 안에 있는 지시문을 실행할  어떤 인터프리터를 사용할 것인지 리눅스에게 알려주는 것이므로 번역기를 정확하게 명시하는 것은 매우 중요하다다음엔  스크립트를 hello.sh 이름으로 저장하자.모두  되었으면스크립트를 실행 가능하도록 한다:

xconsole$ chmod 700 ./hello.sh

파일의 퍼미션을 어떻게 바꾸는지 모른다면 chmod 대한 매뉴얼 페이지를 참조하라일단 위의 명령을 실행하면 단지 파일 이름을 타이핑하는 것만으로 당신의 프로그램을 실행할  있다:

xconsole$ ./hello.sh
Hello World

됐다당신의 첫번째 프로그램이다 자체로는 지루하고 쓸모없지만모든 사람이 이런 식으로 프로그래밍을 시작한다첫번째 프로그램을 실행하기까지의 과정을 되새겨 보자코드를 작성하고파일을 저장하고, chmod 명령으로 실행 가능하도록 만들었다.

명령들명령들명령들 
당신의 첫번째 프로그램이  일은 정확히 무엇인가 프로그램은 화면에 "Hello World" 문구를 프린트했다하지만 어떻게 그렇게  것일까프로그램은 명령을 사용했다프로그램 상에서 당신이 썼던   줄의코드는 echo "Hello World"였다그렇다면어떤 것이 명령인가바로 echo이다echo 프로그램은 하나의 인자를 취해서  인자를 화면에 프린트한다.

인자(argument) 프로그램 이름을 입력한 다음에 따라온다첫번째 예제에서 당신이echo 넘겨  인자는 "Hello World"이다당신이 ls /home/root 명령을 입력할 ls 대한 인자는 /home/root이다그렇다면  모든것이 뜻하는 것은 무엇인가만일 당신이 인자 하나를 취해서 화면에 프린트하는 프로그램을 가지고 있다면 프로그램 대신에 echo 사용할  있다는 것이다우리가 foo라고 하는 프로그램을 가지고 있다고 가정하자 프로그램은 문자열 하나를 인자로 가져서  화면에 출력한다우리는 위의 예제를 다음과 같이 다시   있다:

#!/bin/bash
foo "Hello World"

 내용을 저장하고 chmod  실행 가능하도록 하여 실행하자:

xconsole$ ./hello
Hello World

결과는 정확하게 똑같다프로그램 이름을 제외하고 어느  곳이라도 다른 곳이 있는가전혀 없다실제로 무엇인가 작성한 것이 있는가당신이 echo 프로그램을 작성했다면 모르지만 그렇지 않다면 전혀 작성한 것이 없다당신이  것이라고는 이미 주어진 인자와 함께 echo 프로그램을 당신의  프로그램에 사용한  뿐이다실제로 echo 명령 대신   있는 명령은 printf  있다특히 C 프로그래밍에 능한 사람의 경우에는printf 여러 기능을 이용해서 보다 다양한 결과를   있다사실 프로그램을 만들지 않고도 위의 예제와  같은 결과를 얻을  있다:

xconsole$ echo "Hello World"
Hello World

bash  스크립팅은 다양한 제어를 가능하게 하며 또한 배우기 쉽다방금 보았듯이 프로그램에 리눅스 명령을 함께   있다 프로그램은 특정한 일을 하기 위해 특별히 조립된 여러 프로그램의 집합체이다.

보다 유용한 프로그램 
이제 우리는 모든 파일을 하나의 디렉토리로 옮기고 디렉토리를 내용물 모두와 함께 지운 다시  디렉토리를 만드는 프로그램을 만들 것이다 작업은 다음의 명령들을 통해 이루어질  있다:

xconsole$ mkdir trash
xconsole$ mv * trash
xconsole$ rm -rf trash
xconsole$ mkdir trash

위의 명령을  상에서 대화식으로 입력하는 대신 프로그램을 작성하자:

#!/bin/bash
mkdir trash
mv * trash
rm -rf trash
mkdir trash
echo "Deleted all files!"

위의 내용을 clean.sh으로 저장하자이제 당신이 해야  일은 clean.sh 실행하는 것뿐이다clean.sh 모든 파일을 trash디렉토리로 옮기고, trash 디렉토리를 삭제하고는 다시 만든 모든 파일이 성공적으로 삭제되었다는 메시지까지 출력한다만일 당신이 명령을 입력하고 기다렸다가 다시 입력해야 하는 일을 해야 한다면 프로그램으로 자동화하는 방법을 고려하라.

주석 
주석을 달면 코드 읽기가 보다 쉬워진다주석을 단다고 해서 프로그램의 출력에 영향을 주지 않는다코드를 읽는 사람을 위해 주석은 특별히 만들어졌다. bash에서 첫번째 라인(#!/bin/bash) 제외한 모든 주석은 해쉬심벌("#") 시작한다첫번째 라인은 주석이 아니다첫번째 라인 다음에 오는 "#"으로 시작하는 모든 라인은 주석이다다음의 코드를 보자:

#!/bin/bash
 프로그램은 1부터 10까지 카운트한다:
for i in 1 2 3 4 5 6 7 8 9 10; do
    echo $i
done

만일 당신이 bash 스크립팅을 모른다고 해도주석 때문에 위의 프로그램이 무엇을 하는지 바로   있다주석을 적절하게 이용하는 것은 좋은 습관이다만일 훗날 당신의 프로그램을 유지 보수할 필요가 있다면주석을 달아 놓는 것이 일을 얼마나 편하게 만드는지 알게  것이다.

 

변수
변수는 기본적으로 값들을 담고 있는 "상자"이다당신은 많은 이유로 인해 변수들을 만들고 싶어할 것이다사용자 입력인자들또는 수치 값을 보관하기 위해 변수들이 필요하다다음 짧은 코드를 예로 들자:

#!/bin/bash
x=12
echo "The value of variable x is $x"

여기서  일은x 값을 12 정한 것이다echo "The value of variable x is $x" 이라는 라인은 x 현재 값을 프린트한다변수를 정의할 할당 연산자 "=사이에는 공백 문자가 있으면  된다여기 할당 연산자를 사용하는 문법이 있다:

variable_name=this_value

변수의 값은 변수 이름 앞에 달러 심벌"$" 붙임으로써 얻을  있다위의 예제에서 보듯이x 값을 echo $x  사용해서 얻을  있다.

변수의 타입에는 지역 변수와 환경 변수이렇게  가지가 있다환경 변수들은 시스템에 의해 정해지고 주로 env 명령을 사용해서   있다환경 변수는 특별한 값을 담고 있다예를 들어만일 다음과 같이 입력하면:

xconsole$ echo $SHELL
/bin/bash

현재 사용 중인 쉘의 이름을 얻을  있다환경 변수들은 /etc/profile ~/.bash_profile 안에 정의되어 있다환경 변수이든지지역 변수이든지 현재 변수 값을 체크할  echo 명령이 유용하게 쓰인다여전히  변수가 필요한지 이해하지 못하겠다면여기 좋은 예제가 있다:

#!/bin/bash
echo "The value of x is 12."
echo "I have 12 pencils."
echo "He told me that the value of x is 12."
echo "I am 12 years old."
echo "How come the value of x is 12?"

이제 당신은 x 값을 12 대신 8 하기로 결정했다고 하자어떻게 하겠는가? "x is 12"라고 되어 있는 모든 라인을 바꿔야만 한다잠깐 기다려 보라숫자 12 가진 다른 라인들도 있다 라인들도 바꿔야 하는가아니다그것들은 x 관련이 없으니 그냥 둔다 복잡한가이제여기 변수를 사용한 것만 제외하면  같은 예제가 있다:

#!/bin/bash
x=12     # 변수 x  12 대입한다 
echo "The value of x is $x."
echo "I have 12 pencils."
echo "He told me that the value of x is $x."
echo "I am 12 years old." echo "How come the value of x is $x?"

여기서우리는 $x 변수 x 현재 , 12 프린트하는 것을   있다그래서 만일 x 값을 8 바꾼다면당신이 해야하는 일은 x=12라고 되어 있는 라인을 x=8 바꾸는 일뿐이다그러면 프로그램은 자동적으로 $x 있는 라인을 12 대신 8 바꾸어 보여  것이다다른 라인은 바뀌지 않는다뒤에서 보겠지만변수는 다른 용도로도 중요하게 사용된다.

제어 구조 
제어 구조는 당신의 프로그램을 보다 간결하게 하며프로그램이 결정을 내릴  있게 한다뿐만 아니라더욱 중요한 것은 에러를 체크하도록   있다는 것이다지금까지 우리가  예제는 모두 첫번째 라인에서부터 마지막 라인까지 프로그램의 모든 명령을 실행하는 프로그램이었다예를 들면 다음과 같은 방식이다:

#!/bin/bash
cp /etc/foo .
echo "Done."

이것은 bar.sh 작은 프로그램인데/etc/foo 파일을 현재의 디렉토리로 복사하고는 화면에 "Done"이라고 프린트한다 프로그램은  가지 조건 하에서 작동한다/etc/foo라고 하는 파일이 반드시 존재해야만 한다.그렇지 않다면 다음과 같은 화면을 보게  것이다:

xconsole$ ./bar.sh
cp: /etc/foo: No such file or directory
Done.

당신이 보듯이문제가 있다당신의 프로그램을 실행하는 모든 사람이 그들의 시스템에 /etc/foo라는 파일을 가지고 있지는 않다그래서 /etc/foo라는 파일이 있는지 체크해서 만일  파일이 있으면 복사하도록 하고그렇지 않다면 끝나도록 당신의 프로그램을 수정하는 편이 좋을 것이다의사 코드(pseudo code)  내용을 나타내면 다음과 같다:

만일 /etc/foo 존재하면,
    /etc/foo 현재 디렉토리로 복사한다
    화면에 "Done." 출력한다.
그렇지 않으면
    화면에 "This file does not exist." 촐력한다
    exit

이것을 bash에서   있을까물론bash 제어 구조에는 ifwhileuntilforcase 있다 구조는 시작을 나타내는 starting tag 끝을 나타내는 ending tag 쌍을 이루고 있다예를 들면if 구조는 if 시작해서 fi 끝난다제어 구조는 당신의 시스템에서 발견되어지는 프로그램이 아니다그것들은 bash 내재된 특성이다이러한 제어 구조를 이용해서단지 시스템의 프로그램만을 이용해서  프로그램을 만드는 것에 그치지 않고 당신 자신만의 고유한 코드를 작성할  있다.

if ... else ... elif ... fi
가장 널리 쓰이는 구조  하나가 if 구조이다이것을 이용해서 "만일  조건이 존재한다면 이것을 해라그렇지 않다면다른 것을 해라"라는 방식으로 프로그램이 결정을 내리도록   있다효율적으로 if 구조를 쓰기 위해서우리는 반드시 test 명령을 사용해야 한다test 파일의 존재 여부퍼미션 또는 유사점과 차이점을 체크한다여기 다시 작성한 bar.sh 있다:

#!/bin/bash
if test -f /etc/foo
then
    # 파일이 존재하면복사하고 메시지를 출력한다. 
    cp /etc/foo .
    echo "Done."
else
    # 파일이 존재하지 않으면메시지를 출력하고 프로그램을 종료한다. 
    echo "This file does not exist."
    exit
fi

then else 다음 라인들을 들여  것에 주목하라들여쓰기는 선택 사항이지만그렇게 함으로써 어떤 조건 하에 어떤 라인이 실행될 것인지 눈에  들어와서 코드를 훨씬 쉽게 읽을  있게 된다이제 프로그램을 실행하자만일 당신의 시스템에 /etc/foo 파일이 있다면프로그램은 파일을 복사한다그렇지 않다면에러 메시지를 출력할 것이다test /etc/foo 파일이 존재하는지 체크한다?f 옵션은  인자로 오는 것이 정규 파일인지체크한다다음은 test 옵션 리스트를 보여 주고 있다:

-d 파일이 디렉토리인지 체크 
-e 파일이 존재하는지 체크 
-f 파일이 일반적인 파일인지 체크 
-g 파일이 SGID 퍼미션을 가졌는지 체크 
-r 파일이 읽기 가능인지 체크 
-s 파일의 크기가 0 아닌지 체크 
-u 파일이 SUID 퍼미션을 가졌는지 체크 
-w 파일이 쓰기 가능인지 체크 
-x 파일이 실행 가능인지 체크

else 첫번째 조건이 만족되지 않아서 프로그램이 다른 일을 하도록 하고 싶을  사용된다if 안에  다른 if 사용하고 싶을  사용할  있는 elif 있다기본적으로 elif "else if" 나타낸다첫번째 조건이 만족되지 않았고다른 조건을 테스트하고 싶을  elif 사용한다.

 

만일 다음과 같은if test 구조 형식이 사용하기에 불편하다고 느껴진다면:

if test -f /etc/foo
then

다음과 같이   있다:

if [ -f /etc/foo ]; then

대괄호가 test 역할을 한다당신이 C 프로그래밍에 경험이 있다면 문법이 보다 편안하게 느껴질 것이다양쪽 대괄호 사이에 공백 문자가 있어야 한다는 사실을 염두에 둬라세미콜론 ";" 명령의 끝이라고 쉘에게알려준다세미콜론 뒤에 오는 모든 것은 분리된 라인에 있는 것처럼 실행된다세미콜론을 사용함으로써 보다 읽기 쉬워진다물론 세미콜론을 사용하는 것은 선택 사항이다만일 괜찮다면then 다음 라인에 두자.

test에서 변수를 사용할 따옴표로 변수를 둘러 싸서 사용하는 것은 좋은 생각이다다음의 예를 보자:

if [ "$name" -eq 5 ]; then

while ... do ... done
while 구조는 루프 구조이다기본적으로 while 구조가 하는 일을 말로 표현하면 다음과 같다. " 조건이 참인 동안에는이것을 실행한다조건이  이상 참이 아닐 때까지만". 이제 예제 하나를 보자:

#!/bin/bash
while true; do
   echo "Press CTRL-C to quit." 
done

true 실제 하나의 프로그램이다 프로그램이 하는 일은 중단없이 루프가 계속 돌도록 하는 것이다while 구조에서 true 사용할 때는  프로그램이 true 부른 다음 실행해야 하므로 아무래도 속도면에서 느릴 수밖에 없다하지만 true 대신 ":명령을 사용할  있다.

#!/bin/bash
while :; do
   echo "Press CTRL-C to quit."
done

이것은 정확하게 같은 결과를 보여주지만, ":명령이 bash 안에 내포된 특성이기 때문에 훨씬 빠르다위의 예제가 이전 예제와 다른 점은 읽기가 조금 어려워진 대신 속도가 빨라졌다는 것이다true ":명령   편하게 느껴지는 것을 사용하라다음에 제시되는 변수를 사용하는 예제는 아마도 보다  유용할 것이다:

#!/bin/bash
x=0;     # x 값을 0으로 초기화
while [ "$x" -le 10 ]; do
    echo "Current value of x: $x"
    # x 값을 증가시킨다: 
    x=$(expr $x + 1)
    sleep 1
done

위의 예제에서 보듯이여기서는 test(대괄호 안의 ) 이용해서 변수 x 조건을 체크하고 있다옵션 ?le 만일 x  10 같거나 작은지 체크한다위의 코드를 말로 하면, " x 10 보다 작거나 같은 동안x 현재값을 프린트하고는 x 현재 값에 1 더한다"이다sleep 1  단지 프로그램이 잠깐 쉬도록 한다 문장은 없어도 상관없다 예제에서 하는 일은 상등(equality) 테스트이다만일 변수가 어떤 값과 같은지 체크해서같다면 그에 해당하는 일을 하는 것이다여기서 상등 테스트들의 리스트를 보도록 하자:

숫자들 사이의 상등 체크:
x -eq y   x y 같은지 체크
x -ne y   x y 같지 않은지 체크
x -gt y   x y 보다 큰지 체크
x -lt y   x y 보다 작은지 체크

문자열 사이의 상등 체크:
x = y   문자열 x 문자열 y 같은지 체크
x != y  문자열 x 문자열 y 다른지 체크
-n x   문자열 x  문자가 아니면 true 간주함
-z x   문자열 x  문자이면 true 간주함.

위에서 우리가 작성한 루프 스크립트는 다음의  라인을 제외하면 이해하기에 어렵지 않다:

x=$(expr $x + 1)

위의 명령은 x 값을 1만큼씩 증가시킨다고 알려주고 있다하지만 $(...) 뜻하는 것은 무엇인가변수인가아니다사실이것은 당신이 명령 expr $x + 1  먼저 실행하고 결과를 다시 x 값으로 하기 원한다고 쉘에게 알려주는 방법이다어떤  명령이든 $(...)으로 둘러 싸인 명령은 먼저 실행된다:

#!/bin/bash
me=$(whoami)
echo "I am $me."

 예제를 실행해보면 내가 말하는 바를 이해하게  것이다위의 예제는 다음과 같이 쓰여질 수도 있는데 결과는 같다:

#!/bin/bash
echo "I am $(whoami)."

어느 쪽이 보다 읽기 쉬운지는 당신이 결정하라명령을 실행하거나 명령의 결과를 변수에 대입하는 다른 방법이  있다이것은 뒤에서 설명하도록 하겠다지금은 $(...) 사용하자.

until ... do ... done
until 구조는 while 구조와 매우 유사하다 하나의 차이점은 조건이 반대라는 점이다while 구조는 조건이 참인 동안은 계속해서 반복되지만 until 구조는 조건이 참이  때까지 반복된다그래서 기본적으로 until 구조는 " 조건이 참이  때까지이것을 해라"라는 구조이다다음 예제 하나를 보도록 하자:

#!/bin/bash
x=0
until [ "$x" -ge 10 ]; do
    echo "Current value of x: $x"
    x=$(expr $x + 1)
    sleep 1
done

아마도  짧은 코드는 어디서  듯할 것이다한번 실행해서 결과가 어떻게 나오는지 보라기본적으로until x 10 보다 크거나 같게  때까지 계속해서 반복할 것이다x 값이 10 이르게 되면루프는 정지할것이다따라서마지막에 프린트 되는 x 값은 9  것이다.

for ... in ... do ... done
for 구조는 일정 범위의 변수 안에서 루프를   사용된다예를 들자면 초마다 10개의 점을 프린트하는 작은 프로그램을 작성할  for 사용할  있다:

#!/bin/bash
echo -n "Checking system for errors"
for dots in 1 2 3 4 5 6 7 8 9 10; do
    echo -n "."
    echo "System clean."
done

모르는 사람도 있을  있으므로-n 옵션에 대해 설명하자. -옵션은 echo  사용  자동적으로 개행 문자가 더해지지 않도록 하기 위해 사용된다한번은 ?n 옵션을 가지고 한번은 없이 실행해보면 내가 말하는 것이 무엇인지   있을 것이다변수 dots 1부터 10까지의 값을 갖고 루프를 돌면서  값마다  하나씩을 프린트한다변수가 값을 갖고 루프를 돈다는 것이 무엇을 뜻하는지 보기 위해 다음의 예제를 해보자:

#!/bin/bash
for x in paper pencil pen; do
    echo "The value of variable x is: $x"
    sleep 1
done

프로그램을 실행할  처음엔 x paper 값을 갖고다음엔 pencil 다음엔 pen이란 값을 갖는 것을   있다 이상의 값이 없을 루프는 끝난다.

여기   유용한 예제가 있다다음 프로그램은 현재 디렉토리에 있는 모든 파일에 .html 확장자를 붙인다:

#!/bin/bash
for file in *; do
    echo "Adding .html extension to $file..."
    mv $file $file.html
    sleep 1
done

* 와일드 카드 문자이다. * 뜻하는 것은 "현재 디렉토리의 모든 "으로  예제에서는 현재 디렉토리의 모든 파일을 뜻한다 프로그램을 실행하면 현재 디렉토리의 모든 파일 뒤에 .html 확장자가 붙게 된다변수 file 모든 값을 가지면서 루프를 돈다는 것을 상기하라 경우에는 현재 디렉토리의 파일들을 값으로 갖는다mv 변수 file 값을 .html 확장자를 가진 이름으로 수정하는데 사용된다.

case ... in ... done
case 구조는 if 구조와 매우 유사하다기본적으로 체크 해야할 조건이 많고 if 문을 계속해서 쓰고 싶지 않을  case 구조는  위력을 발휘한다다음의 짧은 코드를 보자:

#!/bin/bash
x=5     # x 값을 5 초기화
이제 x 값을 체크한다: 
case $x in
   0) echo "Value of x is 0."
      ;;
   5) echo "Value of x is 5."
      ;;
   9) echo "Value of x is 9."
      ;;
   *) echo "Unrecognized value."
esac

case 구조는 x 값에 대해서  가지의 가능성을 체크할 것이다 예제에서는 처음에 x 값이 0인지 체크   값이 5인지 체크하고 다음에는 9인지 체크한다마지막으로 앞의 모든 경우에 해당하지 않는다면, "Unrecognized value."라는 메시지를 출력한다. "*" "모든 " 뜻한다고 했던 것을 기억하라 예제에서는 "앞서 명시되었던 값이 아닌 모든 " 뜻한다만일 x 값이 0, 5, 9 아닌 다른 값이라면  값은 * 범주에 들어가게 된다case 사용할  조건은 반드시  개의 세미콜론으로 끝나야 한다if   있는데도  case 사용하는가여기 if 사용해서 작성한 위의 예제와  같은 프로그램이 있다어느 쪽이 작성하기 쉬우며 읽기 쉬운지 비교해 보라:

#!/bin/bash
x=5     # x 값을 5 초기화 
if [ "$x" -eq 0 ]; then
    echo "Value of x is 0."
elif [ "$x" -eq 5 ]; then
    echo "Value of x is 5."
elif [ "$x" -eq 9 ]; then
    echo "Value of x is 9."
else
    echo "Unrecognized value."
fi

인용 부호 
 스크립팅에서 인용 부호는 중요한 부분을 차지한다인용 부호에는  가지 종류가 있다따옴표"작은 따옴표(어포스트로피): ' 따옴표(억음 악센트라고도 ): `  가지이다이들 각각이 의미하는 것이 다른가그렇다.

따옴표는 주로 공백 문자를 포함한 문자열을 담을  이용된다예를 들면, "This string contains whitespace." 보자따옴표로 둘러 싸인 문자열은 하나의 인자로서 취급된다다음의 예제를 보자:

xconsole$ mkdir hello world
xconsole$ ls -F
hello/     world/

 예제에서 우리는  개의 디렉토리를 만들었다mkdir hello  world  개의 인자로 받아들여서  개의 디렉토리를 만든 것이다이제다음과 같이 했을 때의 결과는 어떤지 살펴 보도록 하자:

xconsole$ mkdir "hello world"
xconsole$ ls -F
hello/     hello world/     world/

이번에는 이름이  단어로 이루어진 디렉토리를 만들었다따옴표가  단어를 하나의 인자로 만든 것이다따옴표가 없다면mkdir hello 첫번째 인자로world 두번째 인자로 생각할 것이다.

작은 따옴표는 주로 변수를 다룰 때에 사용된다만일 변수가 따옴표로 둘러싸여 있으면  값의 수치가 구해질 것이다만일 작은 따옴표로 둘러싸여 있으면  값의 수치는 계산되어지지 않는다이것이 뜻하는 바를명확히 하기 위해 다음의 예제를 실행해보자:

#!/bin/bash
x=5     # initialize x to 5
# use double quotes
echo "Using double quotes, the value of x is: $x"
# use forward quotes
echo 'Using forward quotes, the value of x is: $x'

무엇이 차이 나는지 보았는가만일 문자열을 변수로 사용할 계획이 아니라면 따옴표로 둘러싸서 사용할  있다하지만 어떻게   정하지 못했다면 작은 따옴표로도 따옴표처럼 문자열에 공백 문자를 포함하도록 사용할  있다:

xconsole$ mkdir 'hello world'
xconsole$ ls -F
hello world/

 따옴표는 따옴표나 작은 따옴표와는 완전히 다른 용도로 쓰인다공백 문자를 포함하는 데에는 쓰이지 않는다 글의 앞쪽에서 다음 라인을 사용했던 것을 기억해 보라:

x=$(expr $x + 1)

이미 당신이 알듯이명령 expr $x + 1 결과가 변수 x 들어가게 된다 따옴표를 사용한 다음의 명령도  같은 결과를 낸다:

x=`expr $x + 1`

어느 것을 사용해야 하는가 하는 문제는 순전히 당신에게 달려 있다당신이 좋은 쪽을 선택하라 따옴표가 $(...) 보다 자주 사용되는 것을   있을 것이다하지만$(...) 보다 읽기 쉽다다음과 같은 경우엔 특히더 그렇다:

$!/bin/bash
echo "I am `whoami`"

 

BASH에서의 수식 연산 
bash
  수식 표현을 수행할  있도록 해준다이미 보았듯이수식 연산은 expr 명령을 통해서 수행된다그러나expr true 명령과 같이 느린 것으로 생각된다이들 명령이 느린 이유는 이들 명령을 수행하기 위해쉘은 그것들을 시작해야 한다 자체의 내포된 특성을 이용하는 것이 훨씬  빠르다그래서 true 대신에 ":" 사용하는 것을 앞서서 보았다expr 사용하는 대신계산하고자 하는 수식을 $((...)) 안에 쓰면 된다이것은$(...)과는 다르다괄호의 숫자가 다르지 않은가다음 예제를 실행해 보자:

#!/bin/bash
x=8     # x 값을 8 초기화 
y=4     # y 값을 4 초기화
이제 x y 합을 z 대입한다: 
z=$(($x + $y))
echo "The sum of $x + $y is $z"

어떤 것을 선택하든지순전히 당신에게 달려 있다만일 당신이 $((...)) 사용하는 것보다 expr 사용하는 것이 편하다면그것을 사용하면 된다.

bash에서는 덧셈뺄셈곱셈나눗셈모듈러스 계산이 가능하다 계산이 그에 해당하는 연산자를 가지고 있다:

계산              연산자
덧셈                             +
뺄셈                             -
곱셈                             *
나눗셈                          /
모듈러스                     %

처음의   연산자는 모든 사람들에게 익숙할 것이다마지막에 있는 모듈러스는  개의 값으로 나눗셈을   나머지 값을 말하는 것이다다음은 bash에서의 수식 연산에 대한 예제이다:

#!/bin/bash
x=5   # 
x 값을 5 초기화
y=3   # y
 값을 3 초기화

add=$(($x + $y))   # x y 값을 더해서 변수add 대입 
sub=$(($x - $y))   # x 값에서 y 값을 빼서 변수 sub 대입 
mul=$(($x * $y))   # x y 값을 곱해서 변수 mul 대입 
div=$(($x / $y))   # x 값을 y 값으로 나누어 변수div 대입 
mod=$(($x % $y))   # x / y 나머지 값을 구해 변수 mod 대입

답을 출력:
echo "Sum: $add"
echo "Difference: $sub"
echo "Product: $mul"
echo "Quotient: $div"
echo "Remainder: $mod"

위의 예제 코드는 expr 사용해서 다시  수도 있다예를 들면add=$(($x + $y)) 대신에 add=$(expr $x + $y)이나add=`expr $x + $y` 사용할  있다.

사용자 입력 읽기 
이제부터 재미있는 부분이 시작된다당신의 프로그램이 사용자와 대화하도록 만들수 있다사용자로부터 입력을 받아들이는 명령은 read이다read 변수를 사용하는 bash 내포된 명령이다다음의 예를 보자:

#!/bin/bash
사용자 이름을 받아들이고 인사를 출력한다 
echo -n "Enter your name: "
read user_name
echo "Hello $user_name!"

 예제에서 변수는 user_name이다물론 변수 이름은 당신이 좋아하는 다른 것으로 불러도 된다read  사용자가 무엇인가 입력하고는 엔터키를 누르기를 기다린다만일 아무 것도 입력되지 않고 엔터키가 눌러지면,read  코드의 다음 라인을 실행한다한번 해보라여기 사용자가 무엇인가 입력했는지 확인하기 위해 체크하는 것만 제외하고는 위의 예제와  같은 코드가 있다:

#!/bin/bash
사용자 이름을 받아들이고 인사를 출력한다
echo -n "Enter your name: "
read user_name

사용자가 아무 것도 입력하지 않으면:
if [ -z "$user_name" ]; then
    echo "You did not tell me your name!"
    exit
fi

echo "Hello $user_name!"

여기에서만일 사용자가 아무 것도 입력하지 않고 엔터키를 누른다면우리의 프로그램은 불평을 하고는 끝나 버릴 것이다사용자 입력을 받아들이는 것은 사용자가 특정한 것을 입력하도록 하는 대화식 프로그램에유용하게 쓰인다예를 들면간단한 데이터베이스를 만들고 사용자에게 데이터베이스에 들어  내용을 입력하도록   있을 것이다.

함수 
함수를 이용하면 스크립팅은 더욱 쉬워지고 코드는 유지 보수하기가 쉬워진다기본적으로 함수는 프로그램을 작은 조각으로 나눈다함수는 당신이 정의한 일을 수행하고 만일 당신이 원한다면 어떤 값을 리턴할 수도 있다함수에 관한 내용을 계속해서 설명하기 전에함수를 이용한  프로그램의 예를 하나 보기로 하자:

#!/bin/bash

함수 hello()  단지 메시지를 프린트하기만 한다
hello()
{
    echo "You are in function hello()"
}

echo "Calling function hello()..."
함수 hello()  부른다:
hello
echo "You are now out of function hello()"

위의 예제를 실행해 보아라함수 hello()  여기서는 메시지를 프린트하는  하나의 목적을 가지고 있다물론 함수는 보다 복잡한 작업을 하도록 만들  있다위의 예에서우리는 함수 hello() 다음과 같이 이름을이용해서 불렀다:

hello

 라인이 실행되었을 bash hello() 있는 라인을 찾는다 라인을  처음에서 찾자마자hello() 함수의 내용을 실행한다.

위에서 봤듯이함수는 항상 그것의 이름으로 불리워진다함수를 작성할 때는 위에서 했듯이 function_name()으로 시작하거나함수라는 것을 명시하고 싶다면 function function_name()으로 시작할  있다함수 hello() 다음과 같이 작성할 수도 있다:

function hello()
{
    echo "You are in function hello()"
}

함수는 항상  괄호"()" 가지고 시작해서는  뒤에 시작과 끝을 나타내는 중괄호"{...}" 온다 중괄호는 함수의 시작과 끝을 알려준다중괄호로 둘러싸인 모든 코드는 함수가 불려지면 실행될 것이고 오직  함수에만 속한다함수는 항상 불려지기 이전에 정의되어야 한다다음의 예제는 위의 예제 프로그램의 순서를 바꿔서 함수가 정의되기 전에 부르도록 하였다

#!/bin/bash
echo "Calling function hello()..."
함수hello()  부른다:
hello echo "You are now out of function hello()"

# function hello() just prints a message
hello()
{
    echo "You are in function hello()"
}

위의 예제를 실행한 결과는 다음과 같다:

xconsole$ ./hello.sh
Calling function hello()...
./hello.sh: hello: command not found
You are now out of function hello()

당신이 보듯이에러가 발생했다그러므로항상 코드를 작성할 때는 함수를 처음에 정의하라적어도 함수가 불려지기 전에 정의하라여기 함수를 이용하는  다른 예가 있다:

#!/bin/bash
# admin.sh ? 
관리 도구

함수 new_user()  새로운 사용자 계정을 만든다 
new_user()
{
    echo "Preparing to add a new user..."
    sleep 2
    adduser     # run the adduser program
}

echo "1. Add user"
echo "2. Exit"

echo "Enter your choice: "
read choice

case $choice in
    1) adduser     # 함수 adduser() 부른다 
       ;;
    *) exit
       ;;
esac

 예제가 제대로 실행되기 위해서는당신은 루트 사용자이어야 한다adduser  오직 루트만 실행할  있는 프로그램이기 때문이다짤막한  예제로 함수가 얼마나 유용하게 쓰일  있는지 당신이   있으면좋겠다.

시그널 이용하기 
당신의 프로그램에서 시그널을 붙잡아 이용하기 위해서 내포된 명령인 trap   있다이것은 프로그램이 실행되고 있는 도중에 갑자기 아무런 메시지도 없이 끝나 버리는 일없이 우아하게 종료시킬  있는 좋은방법이다예를 들어 보자만일 당신이 프로그램을 실행하고 있는 중이라면CTRL-C 누르는 것은 프로그램에게 인터럽트(interrupt) 시그널을 보낸다인터럽트 시그널은 프로그램을 강제로 종료 시킨다trap 명령을 사용하면  시그널을 잡아내서 프로그램을 계속할 것인지 아니면 사용자에게 프로그램을 종료한다는 메시지를 보내도록 하든지 하는 선택을   있다trap 다음의 문법으로 사용된다:

trap action signal

action  시그널을 잡아 냈을  당신이 수행하고 싶은 일이고 signal 잡아 내고자 하는 시그널이다시그널의 리스트는 trap ?l 명령으로   있다당신의  프로그램에서 시그널을 이용할 시그널의 처음  글자보통은 SIG 생략한다예를 들면인터럽트 시그널은 SIGINT이지만 다음에 보게  예제에서는 INT만을 이용한다시그널 이름에 덧붙여진 시그널 번호를 이용해도 된다예를 들어SIGINT 수치 값은 2이다.다음의 프로그램을 실행해 보자:

#!/bin/bash
trap 명령을 이용하기

# CTRL-C  붙잡아고 함수 sorry() 실행:
trap sorry INT

함수 sorry() 메시지를 출력한다 
sorry()
{
    echo "I'm sorry Dave. I can't do that."
    sleep 3
}

# 10부터 1까지 카운트: 
for i in 10 9 8 7 6 5 4 3 2 1; do
    $i seconds until system failure."
    sleep 1
done
echo "System failure."

이제프로그램이 실행되어 카운트 다운을 하고 있는 동안에CTRL-C 누르자그러면 프로그램에 인터럽트 시그널이 보내질 것이다하지만 시그널은 trap 명령에 의해 붙잡히고, trap 명령은 sorry() 함수를 실행할것이다action 자리에 "'' 둠으로써 trap 시그널을 무시하도록   있다또한 "-" 써서trap 리셋할 수도 있다 예를 보자:

# 만일 SIGINT 시그널이 붙잡히면 함수sorry() 실행한다:
trap sorry INT

# trap 리셋한다:
trap - INT

# SIGINT 붙잡혀도 아무 것도 하지 않도록 한다:
trap '' INT

trap 리셋하면 프로그램을 인터럽트하고 강제로 종료하는 원래의 작업이 시행된다trap 아무 것도 하지 않도록 하면 들어온 시그널을 무시하고 프로그램은 계속 실행된다.

AND  OR
앞에서 제어 구조의 사용과  유용성에 대해 살펴 보았다거기에 더해질  있는  가지 내용이  있다바로 AND "&&" OR "||구문이다. AND 구문은 다음과 같다:

조건_1 && 조건_2

AND 구문은 처음에 가장 왼쪽에 있는 조건을 체크한다만일 참이라면 번째 조건을 체크한다 번째 조건도 참이라면나머지 코드가 실행된다만일 조건_1 거짓이라면 조건_2 실행되지 않는다말로 풀어쓰면:

만일 조건_1 참이면그리고 만일 조건_2 참이면그렇다면...

AND 구문을 사용하는 예제를 보도록 하자:

#!/bin/bash
x=5
y=10
if [ "$x" -eq 5 ] && [ "$y" -eq 10 ]; then
    echo "Both conditions are true."
else
    echo "The conditions are not true."
fi

여기서, x y,  변수 모두 우리가 체크하는 값들을 가지고 있으므로 조건들이 참이 된다만일 값을 x=5 x=12 바꾸고 다시 프로그램을 실행시키면이제는 조건이 거짓이 된다.

OR 구문도 비슷한 방식으로 사용된다  가지 차이점은 가장 왼쪽의 조건이 거짓인지 체크한 다음에  다음 조건을 체크한다는 사실이다:

조건_1 || 조건_2

의사 코드로 이것을 번역해 보면 다음과 같다:

만일 조건_1 참이라면또는 조건_2 참이라면그렇다면...

그렇기 때문에테스트되는 조건  어느  하나라도 참이면 뒤에 오는 코드는 모두 실행된다:

#!/bin/bash
x=3
y=2
if [ "$x" -eq 5 ] || [ "$y" -eq 2 ]; then
    echo "One of the conditions is true."
else
    echo "None of the conditions are true."
fi

위의 예제에서 개의 조건  하나만이 참이라는 것을   있을 것이다하지만, y 값을 다른 것으로 바꾸고 다시 실행시키면  조건 모두 참이 아니라는 것을   있을 것이다.

AND OR 구문 대신에 if 구조를  수도 있다하지만 그렇게 하면 중첩된(nesting) if 문장들을 쓰게 된다중첩되었다는 (nesting) if 구조 안에  다른 if 구조가 있는 것을 말한다물론 다른 제어 구조를 중첩해서쓰는 것도 가능하다다음은 앞선 AND 코드와 같은 내용을 중첩된 if 구조를 이용해서 다시 작성한 것이다:

#!/bin/bash
x=5
y=10
if [ "$x" -eq 5 ]; then
    if [ "$y" -eq 10 ]; then
        echo "Both conditions are true."
    else
        echo "The conditions are not true."
    fi
fi

 코드는 AND 구문을 사용하는 것과 같은 목적으로 작성된 것이지만 AND 구문보다 읽기가 어렵고 작성하는데 보다 많은 시간이 걸린다. AND OR 구문을 이용하는 것이  현명하다.

인자(argument) 사용하기 
리눅스 프로그램의 대부분이 비대화식이라는 것을 알고 있을 것이다프로그램들은 인자를 입력하도록 요구하고만일 인자를 입력하지 않으면 "usage" 메시지를 출력한다more 명령을 예로 들자만일 more 명령 다음에 파일 이름을 입력하지 않으면바로 "usage메시지를 내보낸다당신의  프로그램이 인자들에 대해 일하도록 하는 것은 가능하다그렇게 하기 위해서, "$#변수를 알아야만 한다 변수는 프로그램에 넘겨지는인자들의  개수를 나타낸다예를 들어다음의 프로그램을 실행시킨다면:

xconsole$ foo argument

$# 1이라는 값을 가질 것이다프로그램 foo 넘겨지는 인자가 하나뿐이기 때문이다만일 인자가  개라면, $# 2라는 값을 가질 것이다뿐만 아니라명령 라인의  단어들프로그램 이름( 경우엔foo)과인자들은  프로그램 안에서 변수로 사용될  있다foo $0 되고 argument $1 된다변수는 최고 9개까지 가능한데프로그램 이름인 $0  뒤의 인자 하나 하나에 대응되는 $1부터 $9까지를 변수로 가질 수있다다음의 예제를 보도록 하자:

#!/bin/bash
첫번째 인자를 출력한다 
처음에 인자를 갖는지 체크한다:
if
 [ "$#" -ne 1 ]; then
    echo "usage: $0 "
fi

echo "The argument is $1"

 프로그램을 실행하기 위해서는 오직  개의 인자를 필요로 한다만일 하나보다 작거나 많은 인자를 입력하면 프로그램은 usage 메시지를 출력할 것이다그렇지 않고  개의 인자를 프로그램에 건네면  프로그램은 당신이 건넨 인자를 출력할 것이다$0 프로그램의 이름이므로 "usage메시지에 사용된다마지막 라인에서 $1 사용하고 있다$1 프로그램에 넘겨지는 인자의 값이 들어 있다는 것을 기억하라.

출력 재지정과 파이프 
일반적으로당신이 명령을 실행할  출력은 화면에 나타난다예를 들면:

xconsole$ echo "Hello World"
Hello World

출력 재지정(redirection) 출력 방향을 다른 (대부분은 파일)으로 바꿀  있게  준다. ">연산자는 출력의 방향을 재지정할  사용된다화살표를 출력 내용이 가야할 곳으로 생각하면 이해하기 쉽다여기 출력을 파일로 지정한 예제가 있다:

xconsole$ echo "Hello World"> foo.file
xconsole$ cat foo.file
Hello World

 예제에서echo "Hello World" 출력은 foo.file 이름의 파일로 재지정되었다출력 내용이 파일의 내용으로  것을   있다. ">연산자의  가지 문제점은 파일의 내용을 겹쳐 쓴다는 것이다만일 파일 내용을 겹쳐 쓰지 않고 뒤에 덧붙이고 싶다면 어떻게 하면 될까파일 뒤에 덧붙이기 위해서는 반드시 ">>연산자를 써야 한다 연산자는 파일 내용을 겹쳐 쓰지 않고 뒤에 덧붙인다는 점을 제외하면 출력 재지정 연산자와꼭 같다.

마지막으로파이프에 대해 이야기 하자파이프는 프로그램으로부터 나오는 출력 결과를 가져와서다른 프로그램의 입력으로 사용할  있게 한다파이프를 이용하기 위해서는 파이프 연산자: "|" 쓰면 된다. "|"는영문자 "L" 소문자가 아니다파이프 연산자는 SHIFT-\ 이용해서 얻을  있다이제 파이프에 관한 예제를 보자:

xconsole$ cat /etc/passwd | grep xconsole
xconsole:x:1002:100:X_console,,,:/home/xconsole:/bin/bash

 예제에서 우리는 /etc/passwd 파일 전체를 읽은 파이프를 이용해서  출력을 입력 내용  xconsole이란 문자열을 찾는grep 명령의 입력으로 사용하여  문자열을 포함한 라인을 화면에 출력했다마지막 출력을파일에 저장하기 위해 출력 재지정을 함께  수도 있다:

xconsole$ cat /etc/passwd | grep xconsole > foo.file
xconsole$ cat foo.file
xconsole:x:1002:100:X_console,,,:/home/xconsole:/bin/bash

제대로 작동하고 있다/etc/passwd 파일을 읽은 전체 출력 내용을 파이프를 통해서 문자열xconsole  찾는 grep 명령의 입력으로 사용하고는 최종 출력 결과를 리다이렉션해서 foo.file  저장했다 프로그램을 작성할  출력 재지정과  파이프가 유용한 도구로 쓰인다는 것을 알게  것이다.

임시 파일 
때때로 임시 파일을 만들어야  필요가 있을 때가 있다 파일은 임시적으로 어떤 데이터를 갖고 있거나또는 단지 어떤 프로그램과 함께 작동할 수도 있다일단 프로그램의 목적이 달성되면대부분의 임시 파일은 삭제된다파일을 만들 때는 파일의 이름을 주어야만 한다파일을 만들 때의 문제는 새로 만드는 파일 이름과 같은 이름의 파일이 같은 디렉토리 안에 있으면 안된다는 것이다만일 그렇지 않게 되면중요한 데이터를 겹쳐  수도 있다하나뿐인 이름의 임시 파일을 만들기 위해, "$$기호를 파일 이름의 첫머리나 끝에 붙일 필요가 있다예를 들어hello라는 이름을 가진 임시 파일을 만들고 싶다고 하자당신의 프로그램을 실행시키는 사용자 또한 hello라는 파일을 가질  있다고 하면 당신의 프로그램에서 사용하는 임시 파일과 충돌이 일어날  있다hello라는 파일 대신에 hello.$$ 또는 $$hello라는 이름의 파일을 만들어서  하나뿐인 파일을 만들  있다다음을 실행해 보자:

xconsole$ touch hello
xconsole$ ls
hello
xconsole$ touch hello.$$
xconsole$ ls
hello     hello.689

당신의 임시 파일이 있는 것을   있다.

리턴  
대부분의 프로그램은 프로그램을 어떻게 나가느냐에 따라 특정한 값을 리턴한다예를 들면grep 매뉴얼 페이지를 보면 찾고자 하는 문자열을 발견하면 grep 0 리턴하고 그렇지 않으면 1 리턴한다고 나와 있다 프로그램의 리턴 값에 대해 신경을 써야 하는 것인가여러 가지 이유에서이다당신이 특정 사용자가 시스템에 있는지 체크하고 싶다고 하자이것을 체크해  방법 중의 하나는 /etc/passwd 파일 안에 사용자의이름이 있는지 grep 명령을 통해 찾아 보는 것이다찾고자 하는 사용자 이름이 foobar라고 하자:

xconsole$ grep "foobar" /etc/passwd
xconsole$

아무 것도 출력되지 않았다이것이 뜻하는 것은 grep 명령이 찾고자 하는 문자열과 일치하는 것을 찾지 못했다는 것이다만일 일치하는 문자열을 찾지 못했다고 메시지를 출력하면 훨씬  도움이  것이다 때가바로 프로그램의 리턴 값을 얻을 필요가 있는 때이다프로그램의 리턴 값은 특별한 변수가 가지고 있다 변수는 $?이다다음의 짧은 코드를 보도록 하자:

#!/bin/bash
사용자 foobar  찾고 모든 출력을 파이프를 통해 /dev/null 보낸다:
grep "foobar" > /dev/null 2>&1
리턴 값을 받아서 그에 해당하는 코드를 실행한다: 
if [ "$?" -eq 0 ]; then
   echo "Match found."
    exit
else
    echo "No match found."
fi

이제 프로그램을 실행하면grep 리턴 값을 붙잡을 것이다만일  값이 0 같다면일치하는 문자열이 발견된 것이어서 그에 해당하는 메시지가 출력된다그렇지 않으면일치하는 문자열이 없다고 메시지를 출력한다이것은 프로그램의 리턴 값을 받아 이용하는 가장 기초적인 예제이다계속해서 연습하다 보면당신이 원하는 것을 하기 위해서 프로그램의 리턴 값이 필요한 때가 많을 것이다.

그렇다면 프로그램이 종료되는 상황에 따라 당신의  스크립트가 특정한 값을 리턴하게 하고 싶다면 어떻게 해야 하는가exit 명령은 리턴할 값을 하나의 인자로서 가진다일반적으로 숫자 0 성공적인 종료에러가 하나도 없이 프로그램이 끝났음을 가리킨다일반적으로 0보다 크거나 작은 숫자는 에러가 생겼음을 뜻한다리턴 값을 정하는 문제는 프로그래머가 결정할 문제이다다음의 프로그램을 보자:

#!/bin/bash
if [ -f "/etc/passwd" ]; then
    echo "Password file exists."
    exit 0
else
    echo "No such file."
    exit 1
fi

exit 리턴 값을 명시하였으므로 스크립트를 이용하는 다른  스크립트에서는  스크립트의 리턴 값을 붙잡아 사용할  있다.

수치 값인 인자 하나를 갖는 return 명령을 이용해서함수들도 값을 리턴할  있다함수에 적용된다는 점을 제외하면 exit 사용되는 방식과  같은 방법으로 return 이용할  있다다음 예를 보자:

check_passwd()
{
    # passwd 
파일이 존재하는지 체크
    if [ -f "/etc/passwd" ]; then
       echo "Password file exists."
        # 
존재하면 0을 리턴한다
       return 0
   else
        # 
존재하지 않는다면 1을 리턴한다
       echo "No such file."
       return 1
   fi
}

함수 check_passwd()로부터 리턴 값을 얻는다: 
foo=check_passwd
값을 체크한다: 
if [ "$foo" -eq 0 ]; then
    echo "File exists."
    exit 0
else
    echo "No such file."
    exit 1
fi

코드를 자세히 보라이해하기 어렵지 않다함수 check_passwd() 리턴 값을 가지는 foo라는 이름의 변수를 가지고 시작한다함수 check_passwd()에서 우리는 /etc/passwd 파일이 존재하는지 체크한다만일 존재한다면, 0 리턴하고그렇지 않으면 1 리턴한다이제 함수를 빠져 나오고 리턴된 값이 0이면 변수 foo 값은 0이다만일 1 리턴되면변수 foo 값은 1이다 예제에서  다음에 행해진 일은 변수 foo 값을 체크해서그에 해당하는 메시지를 프린트하고 0(성공한 경우또는 1(실패한 경우) 리턴 값을 가지고 종료한다.

결론 
이것으로 bash 스크립팅에 관한 소개를 마치고자 한다하지만 당신의 스크립팅 공부는 아직 끝나지 않았다 알아야  것이 많다내가 말한 대로 글은 bash 스크립팅에 관한 소개의 글이지만 당신이  프로그램을 수정하고 당신 자신의  프로그램을 작성하기 위한 디딤돌이 되기에는 충분하다Learning the bash shell, 2nd Edition by O'Reilly & Associates, Inc 구입하기를 강력히 추천하는 바이다bash 스크립팅은 매일 매일의 관리자 작업을   사용하기에 매우 훌륭하다하지만 당신이    프로젝트를 계획하고 있다면, C Perl 같은 보다 강력한 언어를 사용하기 원할 것이다행운을 빈다.

X_console shellscope@yahoo.com