240119 셸 스크립트(if, test, 문자열/정수/파일 비교, 연산자, &&와 ||, for, case, while, until, 함수)
if와 종료 상태
조건식처럼 보이는 [ 는 사실 명령어이고, 다음에 오는 전달된 조건식을 판정해서
참이면 0 종료상태를, 거짓이면 0 이외를 반환한다.
$ [ “$1” = “bin” ]
위 명령어를 셸에 그냥 쳐도 [ 가 명령어이므로 잘 입력이 된다.
$ echo $?
다음에 위 명령어를 수행하면 종료상태가 나온다.
즉 [ ]는 조건식이 아닌 명령어로 봐야 한다.
그러나 꼭 [ ] 를 이용해야만 조건식을 판정할 수 있는 것은 아니다.
ex) grep는 검색어가 조회될 때만 0으로 간주된다.
test 명령어로 [ ] 대신하기
$ if [ “$1” = “bin” ]
은 대체 가능하다.
$ if test “$1” = “bin”
위처럼 대괄호 대신 test로 대체해도 0, 이외의 숫자를 판정한다.
셸에서 문자열 비교하기
str1 = str2 → str1과 str2는 같다
str1 != str2 → str1과 str2는 다르다
-n str1 → str1은 null이 아니다
-z str1 → str1은 null이다
아래는 사용 예시다.
comparison.sh
filename=$1 # 첫 파라미터를 filename에 대입
if [ -z "$filename" ]; then # 만약 filename이 null이라면(받은게 없다면)
filename="default.dat" # default.dat를 집어넣고 종료.
fi
echo $filename
파라미터가 없을 때는 default.dat이 입력되고
파라미터가 있을 때는 그 값을 입력한다.
정수 비교하기
정수는 일단 기본적으로 왼쪽 오른쪽에 숫자를 각각 배치하고
옵션을 가운데 둬서 비교한다.
정수1 -eq 정수2 → 정수1, 2는 같다. ==
-ne → 다르다. !=
-lt → less than(왼쪽기준) 정수1이 2보다 작다. <
-gt → greater than 정수1이 2보다 크다. >
-le → 정수1이 2보다 작거나 같다. <=
-ge → 정수1이 2보다 크거나 같다. >=
아래의 예시는 입력받은 2개의 정수를 비교해서 더 큰 정수 하나만 변수에 저장하는 셸 스크립트이다.
if_int.sh
#!/bin/bash
num1=$1
num2=$2
max=$num1
if [ "$num1" -lt "$num2" ]; then
max=$num2
fi
echo $max
단, 위 셸스크립트는 정수가 아닌 파라미터를 전달받을 시 에러가 난다.
파일비교
조건식에 종종 파일의 상태에 따라 갱신 여부를 정하거나
특정파일이 없으면 생성해주는 경우가 많다.
아래는 파일 비교 시 사용하는 조건비교이다.
-e file
: 파일이 존재한다.
-d file
: 파일이 존재하고 디렉터리다
-h file
: 파일이 존재하고 심볼릭링크다.
-L file
: 위와 상동
-f file
: 파일이 존재하고 일반파일이다.
-r file
: 파일이 존재하고, 읽기권한이 있다.
-w file
: 파일이 존재하고, 쓰기권한이 있다.
-x file
: 파일이 존재하고, 실행권한이 있다.
file1 -nt file2
: file1의 최종변경시각이 file2보다 최근이다.
file1 -ot file2
: 위와 반대
연산자 결합
여러 조건식을 지정할 때는 자바처럼 연산자를 결합할 수 있다.
and, or, not연산자가 있으며 () 를 이용해 우선순위를 다르게 정할 수도 있다.
조건식1 -a 조건식2
: 1 and 2
조건식1 -o 조건식2
: 1 or 2
! 조건식
: not연산자
(조건식3 -a (조건식1 -a 조건식2) ) →
: 조건식1, 2로 and연산후 다시 그 결과와 조건식3의 and연산
&&와 ||를 활용한 명령어 순차평가
명령어1 && 명령어2 는 왼쪽이 참이어야 오른쪽을 마저 실행한다.
즉 왼쪽의 결과를 보고나서야 오른쪽이 실행된다.
예) 파일이 존재하면 cat으로 조회하기
$ [ -f 파일명.txt ] && cat 파일명.txt
존재하지 않는 파일을 입력하니 test1.sh를 조회하지 않는다.
명령어1 || 명령어2 의 경우는 위와 반대로 명령어 1이 거짓일때 명령어2를 실행한다.
파일이 존재하지 않으면 touch로 만들기
$ [ -f 파일명.txt ] || touch 파일명.txt
또한 &&와 ||를 만약 if문에서 사용한다면 and, or연산으로 사용할수도 있다.
있는 파일을 입력할 경우 example2.sh가 생성되지 않지만
없는 파일을 입력했더니 example.sh가 생성되었다.
for문을 통한 반복문 수행
for는 공백이나 탭으로 구분된 구문에 대한 반복 처리를 한다.
기본적으로 아래 문법을 따른다.
for 변수 in 리스트
do
실행구문
done
아래의 예시는 aaa, bbb, ccc를 순차적으로 찍어주는 셸스크립트다.
for_test.sh
for name in aaa bbb ccc
do
echo $name
done
또한 경로에 따라서는 와일드카드를 쓸 수도 있다.
예를 들어 해당 폴더 내의 모든 .sh 파일의 첫 줄을 보여주는 구문은 아래와 같다.
for_text.sh
for filename in *.sh
do
head -n 3 "$filename"
done
for를 쓰지 않고 간단하게 반복시키는 경우는
$ seq 1 5와수행하면 1, 2, 3, 4, 5를 순차적으로 찍어준다.
이를 명령어 치환을 이용한 예시는 아래와 같고 in 우변에 1, 2, 3, 4, 5를 넣어줄 수도 있다.
for_seq.sh
for i in $(seq 1 5)
do
touch "000${i}.txt"
done
ls로 파일, 디렉터리 목록을 확인해 보면 0001~0005.txt 파일이 생성되어 있다.
커맨드라인으로 보낸 인자 일괄처리
$@를 in우변에 사용하면 받은 파라미터를 전부 반복문 타겟으로 잡는다.
parameter_test.sh
#!/bin/bash
for parameter in "$@"
do
echo "$parameter"
done
위 코드는 parameter_test.sh를 실행하며 넘긴 모든 인자를 $@에 받아 처리한다.
case 문
if문보다 분기처리에 좀 더 강점을 가진다.
패턴 뒤에 소괄호를 꼭 넣어줘야 한다.
case 문자열 in
<패턴1>)
처리1
;;
<패턴2>)
처리2
;;
...
esac
case_test.sh
#!/bin/bash
case "$1" in
start | stop)
echo "checked"
;;
*)
echo "unchecked"
;;
esac
위 명령어는 $1의 파라미터가 start 혹은 stop인 경우는 checked를 출력하고
그 외의 경우는 unchecked를 출력한다.
while문
while문은 조건이 참임이 확인되면 한 바퀴 실행 후 또 비교해서 추가 실행여부를 결정한다.
while.sh
#!/bin/bash
i=1
while [ "$i" -le 10 ]
do
echo "$i"
i=$((i + 2))
done
위 구문은 i를 홀수만 출력해서 10보다 작을때까지만 출력하는 구문이다.
until문
while문과 정반대로 조건식이 거짓인 동안만 실행되게 할 수도 있고
while을 until로만 바꾸면 된다.
c언어식 반복문
c언어 사용자에 대한 배려로 c언어 문법으로 반복문을 작동해도 돌아간다.
LIMIT=10
# 괄호는 겹쳐야하고, 겹친괄호내에서는 변수에 $를 왼쪽에 붙이지 않음
for ((a = 1; a < LIMIT; a++)) ;do
echo "$a"
done
셸 내부에서 함수 활용하기
셸에서 함수를 정의해 사용하는것도 가능하다.
아래와 같은 방식을 활용할 수 있다.
function 함수명 (){
실행문;
}
#혹은
function 함수명 {
실행문;
}
#혹은
함수명(){
실행문;
}
위 3가지 중 한 가지 방식을 사용하면 된다.
아래는 3번 방식을 사용한 예제다.
func_test.sh
#!/bin/bash
homesize(){
date
du -h ~ | tail -n 1
}
homesize # 위에는 선언만 한 것이므로 실제로 호출구문이 하나 더 들어가야함.
date와 ~폴더의 정보 중 마지막 1줄만 출력하는 명령어다.
셸 함수는 반드시 호출구문 위쪽에 위치해야 한다.
또한 종료코드는
return 상태코드
ex) return 0
형식으로 전달하면 된다.