본문 바로가기

공부/Linux

[Linux] 셸 스크립트 작성하기

리눅스 환경에서 셸 스크립트를 작성하는 방법을 설명하는 글이다.

Window에서 Ubuntu를 사용한다.

 

 

 

예시 코드를 통해 셸 스크립트를 작성해보자.

 

touch name.sh

 

name.sh를 만든다.

touch: 파일이 없으면 빈 파일을 생성하고 파일이 있으면 파일의 최종 수정 시간을 현재 시간으로 변경

 

 

vi name.sh

 

텍스트 편집기를 연다. i를 눌러 편집 모드에 들어가 아래 코드를 작성해준다.

 

 

#!/bin/sh
echo "사용자 이름: " $USER
echo "홈 디렉터리: " $HOME
exit 0

 

#!/bin/sh: 첫 행에 반드시 써야 하며, 특별한 형태의 주석(#!)으로 배시셸을 사용하겠다는 의미

echo "사용자 이름: " $ USER: echo는 화면에 출력하는 명령어로 '사용자 이름: $USER 환경 변수의 내용'을 출력

exit 0: 종료 코드를 반환, return 0 같은 개념

 

코드를 다 작성하였으면 Esc->:wq->Enter을 통해 빠져나온다. 이제 셸 파일을 실행시켜보자.

 

 


 

 

sh ./name.sh

 

name.sh를 실행한다. 이를 통해 셸 파일이 제대로 실행된 것을 볼 수 있다.

sh: 셸을 실행하는 명령어

 

 

ls -al

 

ls: 현재 디렉터리가 나옴(list)

-al: 숨김파일(.으로 시작하는 폴더)까지 보여줌

해당 명령어를 쳐보면 name.sh가 실행 파일이 아니라는 것을 알 수 있다. 참고로 제일 왼쪽이 x로 끝나야 실행 파일이다.

 

물론 이 때문에 ./name.sh를 통해 name.sh를 실행 시킬 수도 없다. name.sh를 실행 파일로 만들자.

 

 

chmod +x name.sh

 

name.sh 파일을 실행 가능하게 만든다.

chmod: 파일의 권한을 변경하는 명령어

+x: 실행 권한을 추가하는 옵션

 

 

이제 다시 ls -al를 치면 name.sh가 실행 파일로 변한 것을 볼 수 있다. 제대로 실행되는지 확인해보자.

 

./name.sh

 

name.sh를 실행한다. 제대로 작동할 것이다.

 

아래는 간단하게 셸 스크립트 문법을 적어놓겠다.

 

 


 

변수

셸 스크립트에서는 변수를 사용하기 전 미리 선언하지 않으며 처음 변수에 값이 할당되면 자동으로 변수가 생성된다. 변수에 들어가는 모든 값은 문자열로 취급된다. (숫자도 동일) 또한 대문자와 소문자를 구분하며 변수 대입 시 = 앞뒤에 공백이 없어야 한다. $ 등 메타문자(특별한 용도로 사용하는 문자)를 출력하려면 ''로 묶거나 앞에 \를 넣어야 한다.

a = Hello	# 오류: 앞뒤 공백 존재
a=Hello
a=Yes Sir	# 오류: 값의 공백은 ""로 묶어야 함
a="Yes Sir"
a=7+5	# 정상, '7+5'라는 문자열로 인식

 

 

출력할 때는 echo를 쓴다. 입력 시 read를 쓴다.

a="Hello World"
echo $a     # Hello World 출력
echo "$a"	# Hello World 출력
echo '$a'	# $a 출력
echo '\$a'	# $a 출력

read a	# 변수 a에 키보드로 값(문자열 입력)

 

 

파라미터 변수는 $0, $1, $2... 형태이다. 예를 들어 아래 코드를 a.sh라고 저장했다고 하자.

#!/bin/sh
echo "실행파일 이름은 <$0>이다."
echo "첫 번째 파라미터: <$1>, 두 번째 파라미터: <$2>."
echo "명령 전체 파라미터는 <$*> 이다."
exit 0

 

파일을 실행시키자.

 

 

sh a.sh 1번 2번 3번

 

sh: 셸 파일을 실행시킨다.

<$0>엔 a.sh, <$1>엔 1번, <$2>엔 2번, <$*>엔 전체 파라미터인 1번 2번 3번이 들어가 출력된다.

 

 

 


 

조건문

if문

기본 if문에 대해 알아보자.

 

if [ 조건 ]
then
	참인 경우 실행
else
	거짓인 경우 실행
fi

 

주의할 점은[ 조건 ] 안의 각 단어 사이, 대괄호 좌우에 공백이 있어야 한다. 예를 들어보자.

 

 

if [ "cook" = "cook ]
	then
    	echo "참"
fi

 

이렇게 각 단어 사이 공백이 존재해야 한다.

 

비교 연산자에는 다양한 것이 있다. 표로 정리하자.

 

 

문자열 비교 연산자

문자열 비교 설명
"문자열1" = "문자열2" 두 문자열이 같으면 참
"문자열1" != "문자열2" 두 문자열이 같지 않으면 참
-n "문자열" 문자열이 NULL(빈 문자열)이 아니면 참
-z "문자열" 문자열이 NULL(빈 문자열)이면 참

 

 

산술 비교 연산자

산술 비교 설명
수식1 -eq 수식2 두 수식(또는 변수)이 같으면 참
수식1 -ne 수식2 두 수식(또는 변수)이 같지 않으면 참
수식1 -gt 수식2 수식1이 크면 참
수식1 -ge 수식2 수식1이 크거나 같으면 참
수식1 -lt 수식2 수식1이 작으면 참
수식1 -le 수식2 수식1이 작거나 같으면 참
!수식 수식이 거짓이면 참

 

 

관계 연산자

 

관계 연산자 설명
-a(테스트 문 ([ ]) 안에서 사용 가능) 또는 && And(그리고)
-o(테스트 문 ([ ]) 안에서 사용 가능) 또는 || or(또는)

 

파일 관련 조건

파일 관련 조건 설명
-d 파일명 파일이 디렉터리이면 참
-e 파일명 파일이 존재하면 참
-f 파일명 파일이 일반 파일이면 참
-g 파일명 파일에 set-group-id가 설정되면 참
-r 파일명 파일이 읽기 가능이면 참
-s 파일명 파일 크기가 0이 아니면 참
-u 파일명 파일에 set-user-id가 설정되면 참
-w 파일명 파일이 쓰기 가능이면 참
-x 파일명 파일이 실행 가능이면 참

 

 

case~esac

이 다음으론 case~esac문을 배워보자.

 

case 변수 in
    패턴1) 실행할 명령 ;;
    패턴2) 실행할 명령 ;;
    *) 기본 실행 명령 ;;  # (옵션) 모든 경우에 해당하지 않을 때 실행
esac

 

case 변수 in: 비교할 변수를 지정

패턴): 해당 패턴에 맞으면 실행

;;: 명령어 블록 종료

*): 기본값, 모든 경우에 해당하지 않을 때 실행함

esac: case문 종료

 

#!/bin/sh
read answer
case $answer in
	yes | y | Y | Yes | YES)
    	echo "yes를 대답하였습니다."
        echo "종료합니다.";;
    [nN]*)
    	echo "no를 대답하였습니다.";;
    *)
    	echo "yes나 no를 입력하세요";;
esac
exit 0

 

answer을 사용자로부터 입력받고 입력에 따라 다른 문장을 출력한다.

사용자가 yes, y, Y, Yes, YES를 입력한 경우 아래 문장을 출력한다. 명령어가 끝나지 않았으므로 echo "yes를 대답하였습니다." 뒤에는 ;;가 붙지 않는다.

[nN]: n또는 N 중 하나와 일치

*: 뒤에 어떤 문자든 올 수 있음

[nN]*: n 또는 N으로 시작하는 모든 문자열을 의미함.

 

 


 

반복문

for~in문

 

for~in문에 대해 알아보자.

 

for 변수 in 값1 값2 값3 ...
do
	반복할 문장
done

 

반복할 때마다 값이 하나씩 변수에 저장된다.

값은 아래와 같은 유형이 있다.

 

 

단순 리스트 반복

#!/bin/bash

for item in Apple Banana Cherry
do
    echo "과일: $item"
done

 

실행 결과는 아래와 같다.

과일: Apple
과일: Banana
과일: Cherry

 

 

seq를 이용한 숫자 반복

seq는 일정한 범위의 숫자를 생성하는 명령어이다. 

#!/bin/bash

for num in $(seq 1 5)
do
    echo "숫자: $num"
done

 

실행 결과는 아래와 같다.

숫자: 1
숫자: 2
숫자: 3
숫자: 4
숫자: 5

 

 

range를 활용한 숫자 반복

#!/bin/bash

for i in {1..5}
do
    echo "반복: $i"
done

 

실행 결과는 아래와 같다.

반복: 1
반복: 2
반복: 3
반복: 4
반복: 5

 

 

*.txt 파일 반복처리

#!/bin/bash

for file in *.txt
do
    echo "텍스트 파일: $file"
done

 

현재 디렉토리에 있는 .txt 파일을 하나씩 출력한다.

 

 

C 스타일 for 루프

#!/bin/bash

for ((i=1; i<=5; i++))
do
    echo "카운트: $i"
done

 

실행 결과는 아래와 같다.

카운트: 1
카운트: 2
카운트: 3
카운트: 4
카운트: 5

 

 

 

$@를 활용한 반복

스크립트 실행 시 전달된 모든 인자 리스트를 하나씩 순회한다.

#!/bin/bash

for arg in "$@"
do
    echo "입력된 인자: $arg"
done

 

실행 결과는 아래와 같다.

$ ./script.sh apple banana cherry
입력된 인자: apple
입력된 인자: banana
입력된 인자: cherry