BASH SHELL 배쉬 셀





































































Bash 셸

7.1 Bash 쉘 소개



Bash(Borune-again shell)

리눅스, 맥 OS X 등의 운영 체제의 기본 쉘

Bash 문법은 본 쉘의 문법을 대부분 수용하면서 확장

시작 파일(start-up file)

/etc/profile 

전체 사용자에게 적용되는 환경 설정, 시작 프로그램 지정

/etc/bashrc 

전체 사용자에게 적용되는 별명과 함수들을 정의 

~/.bash_profile 

각 사용자를 위한 환경을 설정, 시작 프로그램 지정 

~/.bashrc 

각 사용자를 위한 별명과 함수들을 정의 

Bash 시작 과정

시작 파일 예

# .bash_profile 

# 사용자의 환경변수 설정 및 시작 프로그램 

if [ -f ~/.bashrc ]

then 

. ~/.bashrc 

fi 


PATH=$PATH:$HOME/bin:.

BASH_ENV=$HOME/.bashrc 

export USERNAME BASH_ENV PATH 


# .bashrc 

# 사용자의 별명 설정 

alias rm='rm -i' 

alias cp='cp -i' 

alias mv='mv -i' 

alias ll='ls -al --color=yes' 

# 시스템 시작 파일 실행

if [ -f /etc/bashrc ]

then 

. /etc/bashrc 

fli


$ alias


7.2 별명 및 히스토리 기능




별명

alias 명령어

스트링이 나타내는 기존 명령에 대해 새로운 단어를 별명으로 정의 

$ alias 단어=스트링 

$ alias dir=ls -aF

$ dir


$ alias h=history

$ alias list=ls –l [--color=auto]


현재까지 정의된 별명들을 확인

$ alias # 별명 리스트

dir ls -aF

h history

list ls –l


이미 정의된 별명 해제

$ unalias 단어 


히스토리

입력된 명령들을 기억하는 기능

$ history [개수]


기억할 히스토리의 크기

$ echo $HISTSIZE

$ HISTSIZE=100

$ echo $HISTSIZE


로그아웃 후에도 히스토리가 저장되도록 설정

$ echo $HISTFILESIZE

$ HISTFIESIZE=100

$ echo $HISTFILESIZE


재실행







$ !! # 바로 전 명령 재실행

$ !999 # 999번 이벤트 재실행

$ !shift # shift로 시작하는 최근 명령 재실행

$ !?.bashrc # .bashrc를 포함하는 최근 명령 재실행


7.3 변수




단순 변수(simple variable)

하나의 값(문자열)만을 저장할 수 있는 변수

$ 이름=단어 

$ city=incheon


변수의 값 사용

$ echo $city

incheon


변수에 어느 때나 필요하면 다른 값을 대입

$ city=seoul


한 번에 여러 개의 변수를 생성

$ country=korea city=incheon


단순 변수

한글 스트링을 값으로 사용

$ country=대한민국 city=인천

$ echo $country $city

대한민국 인천


따옴표를 이용하면 여러 단어로 구성된 스트링을 저장

$ address=“인천시 연수구 송도동” 


리스트 변수(list variable)

한 변수에 여러 개의 값(문자열)을 저장할 수 있는 변수 

$ 이름=( 단어리스트 )

$ cities=(서울 부산 인천)


리스트 변수 사용


리스트 변수 사용 예

리스트 변수 사용

$ echo ${cities[*]}

서울 부산 인천

$ echo ${cities[1]}

서울


리스트의 크기

$ echo ${#cities[*]}     # 리스트 크기

3

$ echo ${cities[3]}


리스트 변수에 새로운 도시 추가

$ cities=(${cities[*]} 제주)

$ echo ${cities[3]}

제주


표준입력 읽기

read 명령어

표준입력에서 한 줄을 읽어서 단어들을 변수들에 순서대로 저장

남은 단어들은 마지막 변수에 모두 저장 

$ read 변수1, ..., 변수n

$ read x y

Merry Christmas !

$ echo $x

Merry

$ echo $y

Christmas !


변수를 하나만 사용

$ read x 

Merry Christmas !

$ echo $x

Merry Christmas !


7.4 지역변수와 환경변수




환경변수와 지역변수

쉘 변수

환경변수와 지역변수 두 종류로 나눌 수 있다 

환경 변수는 값이 자식 프로세스에게 상속되며 지역변수는 그렇지 않다


환경변수와 지역변수 예

$ country=대한민국 city=서울

$ export country

$ echo $country $city

대한민국 서울


$ sh

$ echo $country $city

대한민국

$ ^D


$ echo $country $city

대한민국 서울


사전 정의 환경변수(predefined environment variable)

그 의미가 미리 정해진 환경변수들












$ echo 홈 = $HOME 사용자 = $USER 쉘 = $SHELL

홈 = /home/mysung 사용자 = mysung 쉘 = /bin/bash

$ echo 터미널 = $TERM 경로 리스트 = $PATH

터미널 = ansi 경로 리스트 = /bin:/usr/bin:/usr/local/bin

사전 정의 지역 변수(predefined local variable)

#!/bin/bash 

# builtin.bash

echo 이 스크립트 이름: $0 

echo 첫 번째 명령줄 인수: $1 

echo 모든 명령줄 인수: $* 

echo 명령줄 인수의 개수: $# 

echo 이 스크립트를 실행하는 프로세스 번호: $$

echo 이전 명령의 반환 값: $?


$ chmod +x builtin.bash

$ builtin.bash hello shell

이 스크립트 이름: builtin.sh

첫 번째 명령줄 인수: hello

모든 명령줄 인수: hello shell

이 스크립트를 실행하는 프로세스 번호: 12345

이전 명령의 반환 값: 0



7.5 Bash 쉘 스크립트 





Bash 스크립트 작성 및 실행 과정

(1) 에디터를 사용하여 Bash 스크립트 파일을 작성한다. 

#!/bin/bash 

# state.bash 

echo -n 현재 시간: 

date 

echo 현재 사용자: 

who

echo 시스템 현재 상황: 

uptime

(2) chmod를 이용하여 실행 모드로 변경한다. 

$ chmod +x state.bash  

(3) 스크립트 이름을 타이핑하여 실행한다.

$ state.bash  


if 문

if 문

if 조건식 

then

   명령어리스트

fi


조건식

test 식 

[ 식 ]    (반드시 빈칸)


if `test $# -eq 1`

if [ $# -ne 1 ]


#!/bin/bash

# wc1.bash 파일명

# 명령줄 인수 개수를 확인하고 wc 명령어를 실행

if [ $# -ne 1 ]

then

   echo 사용법: $0 파일

   exit 1

fi

file=$1

wc $file


$ wc1.bash

사용법: wc1.bash 파일

$ wc1.bash wc1.bash

11  30 159 wc1.bash

if-then-else

if-then-else 구문


if 조건식

then

명령어리스트

elif

명령어리스트

else

명령어리스트

fi


#!/bin/bash

# count1.bash [디렉터리] 

# 대상 디렉터리 내의 파일과 서브디렉터리 개수를 프린트

if [ $# -eq 0 ]

then

   dir="."

else

   dir=$1

fi

echo -n $dir 내의 파일과 서브디렉터리 개수:

ls $dir | wc -l


$ count1.bash 

. 내의 파일과 서브디렉터리 개수: 17

7.6 식





비교 연산

산술 비교 연산









문자열 비교 연산 


문자열 비교 연산자

#!/bin/bash

# reply.bash

# 계속 여부를 입력받아 프린트한다

echo -n "계속 하겠습니까 ? "

read reply

if [ $reply == "yes" ]

then

    echo 예

elif [ $reply == "no" ]

then

    echo 아니오

fi


$ reply.bash

계속 하겠습니까 ?아니오

아니오

#!/bin/bash

# reply2.bash

# 계속 여부를 입력받아 프린트한다

echo -n "계속 하겠습니까 ? "

read reply

case $reply in

y*)

    echo 예 ;;

n*)

    echo 아니오

esac


$ reply2.bash

계속 하겠습니까 ?아니오

아니오

파일 관련 연산

파일 관련 연산: 예

if [ -e $file ]

then # $file이 존재하면 

   wc $file

else # $file이 존재하지 않으면 

   echo "오류 ! 파일 없음“

fi 


if [ -d $dir ] 

then

   echo -n $dir 내의 파일과 서브디렉터리 개수:

   ls $dir | wc -l

else

   echo $dir\: 디렉터리 아님

fi 


부울 연산자

조건식에 부울 연산자 사용

! 부정(negation)

&& 논리곱(logical and) 

|| 논리합(logical or) 


# $file이 일반 파일이고 쓸 수 있으면

if [ -f $file ] && [ -w $file ] 

then

   uptime > $file

fi



if [ ! -e $file ]

then # $file이 존재하지 않으면 

   echo $file : 파일 없음 

fi


if [ ! -d $file ]

then # $dir이 디렉터리가 아니면

   echo $file : 디렉터리 아님 

fi


산술 연산

본쉘의 산술 연산


$ a=2+3

$ echo $a

$ a=`expr 2 + 3` # 반드시 빈칸


콘쉘의 let 명령어를 이용한 산술 연산


$ let 변수=수식

$ let a=2*3

$ echo $a

6

$ let a=$a+2

$ echo $a

8

$ let a*=10

$ let b++

산술 연산자



변수 타입 선언

변수 타입 선언: declare 


$ declare -i a # a는 정수형 변수

$ a=12

$ a=a+1 # let 필요 없음

$ echo $a

$ a=12.3 # 오류 메세지

bash: 12.3: syntax error in expression (error token is ".3")

$ declare -r b=23.4 # 읽기 전용 

$ b=23.5 # 오류 메세지

bash: b: readonly variable



7.7 제어구조




Bash 제어구조

조건

if

스위치

case

반복 

for, while, until 


조건문


if 조건식 

then

   명령어리스트

fi


if 조건식 

then

   명령어리스트 

else

   명령어리스트

fi


중첩 조건문 


if 조건식 

then

   명령어리스트 

elif 조건식

then

   명령어리스트 

else

   명령어리스트 

fi

중첩 조건문: 예

#!/bin/bash

# score1.bash 

# 점수에 따라 학점을 결정하여 프린트

echo -n '점수 입력: '

read score

if (( $score >= 90 ))

then

   echo A

elif (( $score >= 80 ))

then

   echo B

elif (( $score >= 70 ))

then

   echo C

else

   echo 노력 요함

fi


$score1.bash

점수 입력: 99

A


스위치

case 단어 in

   패턴1) 명령어리스트;;

   패턴2) 명령어리스트;;

   ...

   *) 명령어리스트;;

esac


#!/bin/bash

# 사용법: score2.bash 

# 점수에 따라 학점을 결정하여 프린트한다.

echo -n '점수 입력: '

read score

let grade=$score/10

case $grade in

   "10" | "9") echo A;;

   "8") echo B;;

   "7") echo C;;

   *) echo 노력 요함;;

esac


반복문: for

for 구문

리스트의 각 값에 대해서 명령어들을 반복


for 이름 [in 단어리스트]

do

   명령어리스트 

done


#!/bin/bash

# for.bash

for color in red yellow green blue

do

  echo one color is $color

done



#!/bin/bash

# invite.bash

# 저녁 초대 메일을 보낸다.

invitee=(mysung stu s1234567) # 자기 ID 추가

for person in $invitee    # Debug!

do

   echo “오늘 저녁식사에 초대합니다 MYS" | \

   mail "${person}"

#   mail "${person}@naver.com"

Done


$ su – stu

암호:

$ mail


모든 명령줄 인수 처리

모든 명령줄 인수 처리 


for file [ in $* ]

do

...

done


단어 리스트가 없으면 대신 $@

#!/bin/bash

# perm1.bash 파일*

# 파일의 사용권한과 이름을 프린트한다 

if [ $# -eq 0 ]

then

   echo 사용법: $0 파일*

   exit 1

fi

echo "사용권한 파일"

for file in $*

do

   if [ -f $file ]

   then

      fileinfo=`ls -l $file`

      perm=`echo "$fileinfo" | cut -d' ' -f1`

      echo "$perm $file"

   fi

done


반복문: while & until

while 문

조건에 따라 명령어들을 반복 실행 


while 조건식

do

   명령어리스트 

done


until 문

조건에 따라 명령어들을 반복 실행 


until 조건식

do

   명령어리스트 

done

#!/bin/bash

# power.bash 

# 2의 1승부터 10승까지 프린트

let i=2

let j=1

while (( $j <= 10 ))

do

   echo '2 ^' $j = $i

   let i*=2

   let j++

done


#!/bin/bash

# power.bash 

# 2의 1승부터 10승까지 프린트

let i=2

let j=1

until ((              ))

do

   echo '2 ^' $j = $i

   let i*=2

   let j++

done


while .vs. until 

#!/bin/bash

# while.bash 

x=1

while [           ]

do

  echo x=$x

  x=`expr $x + 1`

done

#!/bin/bash

# until.bash 

x=1

until [ $x -gt 3 ]

do

  echo x=$x

  x=`expr $x + 1`

done

menu.bash

#!/bin/bash

# 사용법: menu.bash

# 메뉴에 따라 해당 명령어를 실행한다.

echo 명령어 메뉴

stop=0

while (($stop == 0))

do

   cat << MENU

     d : 날짜 시간

     l : 현재 디렉터리 내용

     w : 사용자 보기

     q : 끝냄

MENU

echo -n '? '

read reply

case $reply in

   "d") date;;

   "l") ls;;

   "w") who;;

   "q") stop=1;;

   *) echo 잘못된 선택;;

esac

done


$ menu.bash

명령어 메뉴

d : 날짜 시간

l : 현재 디렉터리 내용

w : 사용자 보기

q : 끝냄

? d

2012년 2월 23일 목요일 오후 07시 33분 27초

d : 날짜 시간

l : 현재 디렉터리 내용

w : 사용자 보기

q : 끝냄

? q


함수

함수 정의

함수이름()

{

   명령어리스트

}


함수 호출

함수이름 [매개변수]


#!/bin/bash

# lshead.bash

lshead() {

echo "함수 시작, 매개변수 $1"

date

echo "디렉터리 $1 내의 처음 3개 파일만 리스트"

ls -l $1 | head -4

}

echo "프로그램 시작"

lshead /tmp # 명령줄 인수로 수정하세요

exit 0


$ lshead.bash

프로그램 시작

함수 시작, 매개변수 /tmp

2012. 10. 31. (수) 14:10:10 KST

디렉터리 /tmp 내의 처음 3개 파일만 리스트

합계 968

-rw-r--r--. 1 s2701367   ul2011a      2 10월 21 02:15 1.c

-rw-r--r--. 1 s2701346   ul2011a      3 10월 23 04:21 12.c

-rw-r--r--. 1 s201101608 ul2011a    298 10월 21 21:39 2.5.c


7.8 고급 기능




디버깅

$ bash -vx 스트립트 [명령줄 인수]


#!/bin/bash

# menux.bash 오류 있는 프로그램

echo 명령어 메뉴

명령어 메뉴

stop=0

while (($stop == 0))

do

   cat << MENU

   echo -n '? '

   read reply

   case $reply in

      "d") date;;

      "l") ls;;

      "w") who;;

      "q") stop=1;;

      *) echo 잘못된 선택;;

   esac

done



$ bash -vx menux.bash

#!/bin/bash

# 사용법: menu.bash

# 메뉴에 따라 해당 명령어를 실행한다.

echo 명령어 메뉴

+ echo $'\270\355\267\311\276\356' $'\270\336\264\272'

명령어 메뉴

명령어 메뉴

+ $'\270\355\267\311\276\356' $'\270\336\264\272'

./menux.bash: line 5: 명령어: command not found

stop=0

+ stop=0

while (($stop == 0))

do

   cat << MENU

echo -n '? '

read reply

case $reply in

   "d") date;;

   "l") ls;;

   "w") who;;

   "q") stop=1;;

   *) echo 잘못된 선택;;

esac

done


./menux.bash: line 20: warning: here-document at line 9 delimited by end-of-file

 (wanted `MENU')

./menux.bash: line 21: syntax error: unexpected end of file


shift

shift 명령어

명령줄 인수[리스트 변수] 내의 원소들을 하나씩 왼쪽으로 이동


shift [리스트변수]


$ chmod +x perm2.bash

$ ./perm2.bash *

$ ./perm2.bash p*


#!/bin/bash

# perm2.bash 파일*

# 파일의 사용권한과 이름을 프린트 

if [ $# -eq 0 ]

then

   echo 사용법: $0 files

   exit 1

fi

echo "허가권 파일"

while [ $# -gt 0 ]

do

   file=$1

   if [ -f $file ]

   then

     fileinfo=`ls -l $file`

     perm=`echo "$fileinfo" | cut -d' ' -f1`

#    perm=`ls -l $file | cut -d' ' -f1`

     echo "$perm $file"

   fi

   shift

done


디렉터리 내의 모든 파일 처리

디렉터리 내의 모든 파일 처리

해당 디렉터리로 이동

for 문과 대표 문자 *를 사용

대표 문자 *는 현재 디렉터리 내의 모든 파일 이름들로 대치


cd $dir

for file in *

do

...

done


$ chmod +x count2.bash

$ ./count2.bash /tmp

$ ./count2.bash /dev

$ mknod mypipe p

$ ./count2.bash ./

재귀적 반복(recursion)

스크립트도 자기 자신을 호출 가능

어떤 디렉터리의 모든 하위 디렉터리에 대해 동일한 작업을 수행할 때 매우 유용함

반드시 절대경로로 호출


$ chmod +x rhead.bash

$ rm a.out

$ ./rhead.bash ./


#!/bin/bash

# rhead.bash [디렉터리]

# 대상 디렉터리와 모든 하위 디렉터리 내에 있는 파일들의 헤더를 프린트

#if [ $# -eq 0 ]

#then

#   echo 사용법: $0 directory

#   exit 1

#fi

#if [ ! -d $1 ]

#then

#   echo $0\: $1 디렉터리 아님

#   exit 1

#fi

cd $1

for file in *

do

   if [ -f $file ]

   then

     echo "========== $file ==========="

     head -3 $file

   fi

   if [ -d $file ]

   then

      /home/mysung/ulprog/shellprog/rhead.bash $file

   fi

done

터미널에서 실행

터미널에서 while 혹은 for 문도 실행


$ for f in *

> do

> echo $f

> done





$ echo $PS2


$ let i=2

$ let j=1

$ while (( $j <= 10 ))

> do

> echo '2 ^' $j = $i 

> let i*=2 

> let j++ 

> done 

2 ^ 1 = 2

2 ^ 2 = 4

2 ^ 10 = 1024


(참고) set

set 옵션

$ set -v (verbose mode)

$ set +v (verbose mode 제거)

$ set -x (실행된 명령에 + +표시, 전달된 매개변수 내용 출력, 디버깅에 좋음)

$ set - (-v와 -x를 무력화 시키고 인수로 매개변수 설정)

$ set -- (double hyphens)로 매개변수 시작 알림

$ set -u (설정되지 않은 변수 만나면 에러 발생)

$ set -k (명령 이름 앞에 적은 것 뿐 아니라, 모든 키워드 인수를 명령의 환경으로 설정)


(예)

$ set - a b c

$ echo $1

$ date

2013. 11. 11. (월) 11:11:11 KST

$ set -- `date`

$ echo $6

KST

$ echo "$@"

2013. 11. 11. (월) 11:11:11 KST

(참고) set

-x 명령 행 옵션으로 실행되는 디버깅 기능

$ cat set.bash

set -vx a.c

ls $1

set -

echo notset=\"$notset\"

echo goodbye $LOGNAME

set -u

echo notset=\"$notset\"

$ set.bash b.c

…?…  실제로 수행된 명령 앞에 ++ 표시


쉘 명령 앞에서 변수 배정 정의하면 그 명령으로 변수 값이 export됨

$ cat myname

echo My name is $name and my argument is $1

$ name=MYS  myname  Jay


set -k로 매개변수를 주어진 모든 키워드(‘=‘) 인수를 명령의 환경에 위치시킴

$ set -k

$ myname  name=MYS  Jay

(참고) junk (= 7장 연습문제 2번 해법)

#! /bin/bash

# junk script

# Initialize variables

fileCount=0     # the number of files specified.

listFlag=0      # set to 1 if the list option (-) is used.

purgeFlag=0     # set to 1 if the purge (-p) option is used.

fileFlag=0      # set to 1 if at least one file is specified.

junk=~/.junk    # the name of the junk directory.

error ()

{

# Display error message and quit

cat << ENDOFTEXT

echo Dear $USER, the usage of junk is as follows:

echo   junk -p means "purge all files"

echo   junk -l means "list junked files"

echo   junk <list of files> to junk them

ENDOFTEXT

exit 1

}

# Parse command line

for arg in $*

do

  case $arg in

    "-p")

        purgeFlag=1        ;;

    "-l")

        listFlag=1        ;;

    "-*")

        echo $arg is an illegal option        ;;

    *)

        fileFlag=1

        fileList[$fileCount]=$arg # append to list

        let fileCount=fileCount+1        ;;

    esac

done




핵심 개념

단순 변수는 하나의 값(문자열)을 리스트 변수는 여러 개의 값 (문자열)을 저장할 수 있다

쉘 변수는 크게 환경변수와 지역변수 두 종류로 나눌 수 있다.  환경 변수는 값이 자식 프로세스에게 상속되며 지역변수는 그렇지 않다

Bash 쉘은 조건, 스위치, 반복 등을 위한 제어구조로 if, case, for, while 등의 문장을 제공한다

Bash 쉘의 식은 비교 연산, 파일 관련 연산, 산술 연산 등을 할 수 있다 





'myPPT' 카테고리의 다른 글

일제의 경제 수탈  (1) 2015.07.06
지구의 생성  (0) 2015.07.04
사회복지의 역사 in 서양 and 한국  (0) 2015.06.29
중국의 현대시 : 시기별 단계  (0) 2015.06.26
전략캔버스 - 가치곡선  (0) 2015.06.24
Posted by MSNU