30 Zsh Script Examples

Zsh 프로그래밍: 30가지 Zsh 스크립트 예제

Zsh 스크립트는 셸 명령을 실행하거나 여러 명령을 일괄 처리하고, 관리 작업을 사용자 정의하거나 작업을 자동화하는 등 다양한 목적으로 사용될 수 있습니다. 따라서 맥/리눅스 사용자라면 Zsh 프로그래밍의 기초를 익혀 두는 것이 중요합니다. 이 글에서는 Zsh 스크립팅 언어의 기본 개념을 다루며, 자주 쓰이는 여러 가지 기능을 간단한 예제를 통해 설명합니다.

1. Hello World

터미널에서 다음 명령을 직접 실행하면 “Hello World”라는 메시지가 출력됩니다.

이제 간단한 Zsh 스크립트를 파일로 작성하고 실행해 보겠습니다. nano 등 편집기로 first.sh 파일을 만든 뒤 다음 내용을 입력하고 저장하세요. 터미널에서  vi 로 편집한 뒤 저장해도 됩니다.

스크립트를 실행하는 방법은 두 가지가 있습니다. 하나는 zsh 셸로 스크립트 파일을 실행하는 방법이고, 다른 하나는 파일에 실행 권한을 주고 직접 실행하는 방법입니다. 아래에 두 가지 방법을 모두 보여줍니다.

(또는 먼저 스크립트에 실행 권한을 준 후 실행할 수도 있습니다)

2. echo 명령 사용하기

echo 명령은 다양한 옵션과 함께 사용할 수 있습니다. 아래 예제에서는 자주 쓰이는 몇 가지 옵션을 보여줍니다. 옵션 없이 echo를 사용하면 출력 후 자동으로 줄바꿈이 들어갑니다. -n 옵션을 사용하면 출력 후 줄바꿈을 생략하고, -e 옵션을 사용하면 백슬래시(\)로 시작하는 이스케이프 문자를 해석하여 특수 문자를 처리할 수 있습니다.

예를 들어, echo_example.sh 라는 새 스크립트 파일에 다음과 같이 작성해 보겠습니다.

위 스크립트를 실행하면 각 옵션의 효과를 확인할 수 있습니다. 여기서 둘째줄을 실행하고 줄바꿈을 하지 않아야하지만, 셋째줄에 \n이 있기 때문에 줄바꿈을 합니다.

3. 주석 사용하기

# 기호는 스크립트에서 한 줄 주석(comment)을 작성할 때 사용합니다. 한 줄에서 # 뒤에 오는 내용은 셸이 실행할 때 무시됩니다. 주석은 스크립트에 설명이나 메모를 남길 때 유용하게 활용됩니다.

예를 들어, comment_example.sh 파일을 만들고 아래와 같이 작성해 보겠습니다. 두 수를 더한 후 결과를 출력하는 스크립트이며, 각 단계 옆에 주석을 달았습니다.

이 스크립트를 실행하면 합계 60이 출력됩니다.

4. 여러 줄 주석

Zsh 스크립트에는 여러 줄을 한꺼번에 주석 처리하는 구문이 따로 없지만, 우회적인 방법으로 여러 줄 주석을 넣을 수 있습니다. 그 중 한 가지 방법은 : (콜론) 명령과 따옴표를 사용하는 것입니다. : 명령은 아무 동작도 하지 않으므로, 그 뒤에 따옴표로 감싼 여러 줄의 텍스트를 넣으면 해당 텍스트는 실행되지 않고 무시됩니다. 이를 이용하면 여러 줄을 한꺼번에 주석처럼 처리할 수 있습니다.

예를 들어, multiline-comment.sh 파일에 다음과 같이 작성해 보겠습니다. 콜론과 따옴표를 활용해 여러 줄 설명을 주석으로 넣었으며, 이 스크립트는 5의 제곱값을 계산해 출력합니다.

위 스크립트를 실행하면 5*5의 계산 결과인 25가 출력됩니다.

5. while 루프 사용하기

Zsh의 while 루프를 사용하면 주어진 조건이 참인 동안 계속해서 명령들을 반복 실행할 수 있습니다. 다음 예제로 이를 확인해보겠습니다. while_example.sh 스크립트에서는 while 루프를 통해 숫자를 5번 출력합니다. 처음에 count 변수를 1로 설정하고, 루프를 반복하면서 count를 1씩 증가시킵니다. 그리고 count가 5와 같아지면 break를 통해 루프를 종료합니다.

위 스크립트를 실행하면 1부터 5까지의 숫자가 한 줄씩 출력됩니다.

6. for 루프 사용하기

Zsh의 for 루프를 사용하면 정해진 목록이나 범위의 값들에 대해 반복 작업을 수행할 수 있습니다. 특히 C 언어 스타일의 for 문법도 사용 가능합니다. 다음 예에서는 for_example.sh 스크립트에서 C 스타일 for 문을 사용하여 counter 변수를 10부터 1까지 감소시키며 반복합니다. 루프가 실행되면서 counter 값을 공백으로 구분해 한 줄에 출력하며, 루프가 끝난 후 printf "\n"를 통해 줄바꿈을 추가합니다.

위 스크립트를 실행하면 10 9 8 ... 1과 같이 10부터 1까지의 숫자가 공백으로 구분되어 한 줄에 출력됩니다.

7. 사용자 입력 받기

read 명령을 사용하면 사용자로부터 값을 입력받을 수 있습니다. 예를 들어, user_input.sh 파일에 다음과 같이 작성해 봅니다. 이 스크립트는 실행 시 사용자에게 이름을 입력하라고 요청한 후, 입력된 이름을 이용해 환영 메시지를 출력합니다.

이 스크립트를 실행한 뒤 이름을 입력하면, 터미널에 해당 이름이 포함된 환영 인사가 표시될 것입니다.

8. if 조건문 사용하기

Zsh에서 if 조건문을 사용하여 특정 조건에 따라 명령을 실행할 수 있습니다. if 문의 시작 블록은 if, 끝은 fi로 표시합니다. 간단한 예로, 변수 n의 값에 따라 다른 메시지를 출력하는 스크립트를 작성해보겠습니다. 아래 simple_if.sh 스크립트에서는 n이 10보다 작으면 “It is a one digit number”를 출력하고, 그렇지 않으면 “It is a two digit number”를 출력합니다. 여기서 숫자 비교를 위해 -lt (less than)를 사용했으며, 이 외에도 -eq (equal), -ne (not equal), -gt (greater than) 등의 비교 옵션을 사용할 수 있습니다.

위 예에서는 n=10이므로 조건이 거짓이 되어, 실행 결과로 It is a two digit number가 출력됩니다. (만약 n이 10보다 작았다면 첫 번째 문장이 출력되었을 것입니다.)

9. if 조건문과 논리 AND

if 문에서 두 가지 이상의 조건을 모두 만족하는지 검사하려면 논리 AND 연산자 &&를 사용할 수 있습니다. 다음 if_with_AND.sh 스크립트는 사용자에게 사용자 이름과 비밀번호를 입력받은 뒤, 입력값이 모두 지정된 문자열과 일치할 경우에만 “valid user”를 출력하고, 그렇지 않으면 “invalid user”를 출력합니다.

예를 들어, 실행 시 사용자 이름에 admin 그리고 비밀번호에 secret를 입력하면 스크립트는 valid user를 출력할 것입니다. 그 외의 다른 값이 입력되면 invalid user를 출력합니다.

10. if 조건문과 논리 OR

두 개 이상의 조건 중 하나만 만족해도 참으로 간주하려면 논리 OR 연산자 ||를 사용할 수 있습니다. 다음 if_with_OR.sh 스크립트는 사용자에게 임의의 숫자를 입력받은 후, 그 숫자가 15이거나 45이면 “You won the game”을 출력하고 그렇지 않으면 “You lost the game”을 출력합니다.

예를 들어, 실행 중에 1545를 입력하면 You won the game 메시지가 표시되고, 다른 숫자를 입력하면 You lost the game 메시지가 표시됩니다.

11. else if (elif) 사용하기

하나의 if 블록 안에서 여러 조건을 차례로 검사하려면 else if 구문을 사용하면 됩니다. Zsh 스크립트에서는 else if 대신 elif 라는 키워드를 사용합니다. 다음 elseif_example.sh 예제 스크립트는 사용자로부터 행운의 숫자를 입력받아, 입력된 숫자가 특정 값일 때 각각 1등, 2등, 3등 당첨 메시지를 출력하고 그 외의 경우에는 낙첨 메시지를 출력합니다.

예를 들어, 실행 시 101을 입력하면 1등 당첨 메시지(“You got 1st prize”)가 출력되고, 510을 입력하면 2등(“You got 2nd prize”), 999를 입력하면 3등(“You got 3rd prize”) 메시지가 출력됩니다. 그 외의 숫자를 입력한 경우에는 Sorry, try for the next time라는 메시지가 표시될 것입니다.

12. case문 사용하기

다중 조건을 처리하는 또 다른 방법으로 case 구문을 사용할 수 있습니다. case 문은 주어진 값이 여러 패턴 중 어느 하나와 일치하는지 검사하여 해당 분기 코드를 실행하며, 복잡한 if-elif-else 구조를 대체하기에 유용합니다. case 블록의 시작은 case, 끝은 esac (case를 반대로 쓴 키워드)로 닫습니다.

이전 예제와 같은 기능을 case로 구현한 case_example.sh 스크립트를 살펴보겠습니다.

위 스크립트의 실행 결과는 앞선 if-elif 예제와 동일합니다. 예를 들어, 입력값이 101이면 You got 1st prize, 510이면 You got 2nd prize, 999이면 You got 3rd prize 메시지가 출력되며, 그 외의 입력에 대해서는 Sorry, try for the next time 메시지를 출력합니다.

13. 명령행 인자 처리하기

스크립트를 실행할 때 인자를 함께 전달하면, 스크립트 내에서 해당 인자들을 활용할 수 있습니다. 각 인자는 특별한 변수로 접근할 수 있는데, $1은 첫 번째 인자, $2는 두 번째 인자를 가리키며 $#는 전달된 인자의 개수를 나타냅니다.

예제로, command_line.sh 스크립트를 작성해 보겠습니다. 이 스크립트는 전달된 인자의 총 개수와 첫 번째, 두 번째 인자의 값을 출력합니다.

예를 들어, 위 스크립트를 $ zsh command_line.sh Hello World처럼 두 개의 인자와 함께 실행하면, 총 인자 개수는 2이고 첫 번째 인자는 “Hello”, 두 번째 인자는 “World”임을 출력할 것입니다.

14. 이름으로 명령행 인자 처리하기

명령행 인자를 이름=값 형태로 전달받아 파싱할 수도 있습니다. 다음 command_line_names.sh 스크립트는 이런 형식의 인자를 처리하는 예제입니다. 스크립트는 전달된 모든 인자를 $@ 리스트로 받아 반복하면서, 각 인자를 = 기호 기준으로 나누어 이름과 값을 추출합니다. 그런 다음 이름이 X이면 변수 x에 값을 대입하고, 이름이 Y이면 변수 y에 값을 대입합니다. 마지막으로 두 값의 합을 계산하여 출력합니다.

예를 들어, 위 스크립트를 $ zsh command_line_names.sh X=45 Y=30 처럼 실행하면 X+Y=75 라는 결과가 출력될 것입니다.

15. 문자열 합치기

여러 문자열 변수를 결합하여 하나의 문자열로 만들 수 있습니다. 변수들을 공백 없이 나열하면 바로 이어붙여지고, += 연산자를 사용하면 기존 문자열에 새로운 문자열을 추가할 수 있습니다. 아래 string_combine.sh 예제에서 $string1$string2처럼 변수를 연속해서 사용하면 두 값이 그대로 연결되어 출력됩니다. 반면 string3=$string1+$string2처럼 변수 사이에 + 기호를 넣으면 플러스 기호가 문자열에 포함됩니다. 이후 string3+=... 구문을 사용하면 해당 변수에 문자열을 이어 붙일 수 있습니다.

이 스크립트를 실행하면 첫 번째 echo 명령으로 LinuxHint가 출력되고, 두 번째 echo 명령으로 Linux+Hint is a good tutorial blog site가 출력되는 것을 확인할 수 있습니다.

16. 문자열 일부 추출하기

Zsh에는 문자열에서 일부 내용을 잘라내는 전용 함수가 없지만, 변수 확장 기능을 사용하여 부분 문자열을 얻을 수 있습니다. 예를 들어 ${변수:시작:길이} 형식을 사용하면 지정한 위치에서 일정 길이만큼의 문자열을 추출합니다. (여기서 시작 위치는 0부터 센 인덱스입니다.) 아래 substring_example.sh 스크립트에서는 변수 Str에서 6번째 문자부터 5글자를 잘라내어 출력합니다.

위 스크립트를 실행하면 Linux가 출력됩니다.

17. 두 수 더하기

Zsh에서 산술 연산을 수행하는 방법은 여러 가지가 있습니다. 그 중 하나는 이중 괄호 (( )) 구문을 사용하는 것입니다. 다음 add_numbers.sh 스크립트는 사용자로부터 두 개의 정수를 입력받아 그 합을 계산한 후 결과를 출력합니다.

예를 들어, 스크립트를 실행하여 57을 입력하면 The result of addition=12와 같은 출력이 나타납니다.

18. 함수 정의 및 호출

Zsh 스크립트에서 특정 작업을 묶어 함수(function)로 정의해두면 필요할 때마다 반복 사용하기 편리합니다. 함수는 function 이름() 또는 단순히 이름() 형태로 선언하며, 중괄호 { } 안에 함수가 수행할 명령들을 적습니다. 정의한 함수는 이후에 함수 이름만 써서 호출할 수 있습니다 (괄호 없이 함수명을 사용).

예를 들어, function_example.sh 스크립트에서 간단한 함수를 정의하고 호출해 보겠습니다.

위 스크립트를 실행하면 함수 F1의 동작에 따라 I like Zsh programming 이라는 문장이 출력됩니다.

19. 함수에 인자 전달하기

타 프로그래밍 언어와는 달리 Zsh의 함수는 정의 시 매개변수를 선언하지 않습니다. 그러나 함수를 호출하면서 값을 전달하면, 함수 내부에서 $1, $2와 같은 변수를 통해 전달된 인자 값을 참조할 수 있습니다. 즉, 호출 시 첫 번째 인자가 함수 내부에서는 $1으로, 두 번째 인자가 $2로 취급됩니다.

예를 들어, function_parameter.sh 스크립트에서 사각형의 넓이를 계산하는 함수를 정의하고 두 인자를 전달해 호출해 보겠습니다.

위 스크립트를 실행하면 Rectangle_Area 10 20 함수 호출에 따라 Area is : 200 이 출력됩니다.

20. 함수의 반환값 활용

일반적으로 Zsh 함수는 문자열을 직접 반환하지 않지만, 함수 내에서 echo로 출력한 내용을 명령 치환($(...))을 통해 호출 측에서 변수에 담을 수 있습니다. 숫자 값의 경우 return 명령을 사용해 상태 코드($?로 확인)를 전달할 수 있지만, 문자열은 이처럼 출력 결과를 이용하는 방식으로 받아옵니다.

다음 function_return.sh 스크립트는 사용자에게 이름을 입력받은 후, greeting 함수에서 환영 문자열을 생성하여 출력하고, 그 값을 호출 부분에서 변수로 받아와 활용하는 예제입니다.

예를 들어, 실행 중 이름으로 Alice를 입력하면 함수 내부에서 Hello, Alice를 출력한 뒤, 마지막에 Return value of the function is Hello, Alice라는 문자열을 출력합니다.

21. 디렉터리 생성하기

터미널 명령인 mkdir를 사용하면 새 디렉터리를 만들 수 있습니다. 다음 make_directory.sh 스크립트는 사용자에게 새 디렉터리 이름을 입력받은 후 mkdir 명령으로 해당 이름의 디렉터리를 생성합니다. (만약 동일한 이름의 디렉터리가 이미 존재하면 오류 메시지가 표시됩니다.)

이 스크립트를 실행하고 디렉터리 이름을 입력하면, 현재 경로에 해당 이름을 가진 새 디렉터리가 생성됩니다.

22. 디렉터리 존재 확인 후 생성

디렉터리를 만들기 전에 같은 이름의 디렉터리가 이미 있는지 확인하고 싶다면 조건문에서 -d 옵션을 사용할 수 있습니다. -d는 괄호 안의 경로가 디렉터리로 존재하면 참(True)을 반환합니다. 다음 directory_exist.sh 스크립트는 입력받은 이름의 디렉터리가 현재 위치에 존재하는지 검사한 후, 존재하면 그 사실을 알리고 존재하지 않으면 mkdir로 디렉터리를 생성합니다.

이 스크립트를 실행하면, 해당 이름의 폴더가 이미 있을 경우 Directory exist라고 출력되고 없을 경우 폴더를 생성한 후 Directory created라고 출력합니다.

23. 파일 읽기

스크립트에서 read 명령과 반복문을 활용하면 텍스트 파일을 한 줄씩 읽어서 처리할 수 있습니다. 다음 read_file.sh 스크립트는 현재 디렉터리에 있는 book.txt 파일을 한 줄씩 읽어 화면에 출력하는 예제입니다.

위 스크립트를 실행하면 book.txt 파일의 내용을 각 줄마다 출력합니다.

24. 파일 삭제하기

rm 명령을 사용하여 파일을 삭제할 수 있습니다. 특히 -i 옵션을 주면 삭제 전에 사용자에게 확인을 요청합니다. 다음 delete_file.sh 스크립트는 사용자로부터 삭제할 파일 이름을 입력받아 해당 파일을 지우기 전에 확인하도록 합니다.

이 스크립트를 실행하고 파일 이름을 입력하면 그 파일을 삭제할지 묻는 메시지가 표시되며, y를 입력하여 확인하면 파일이 삭제됩니다.

25. 파일에 내용 추가하기

리다이렉션 연산자 >>를 사용하면 기존 파일의 끝에 새 데이터를 추가할 수 있습니다. 다음 append_file.sh 스크립트는 book.txt 파일에 한 줄의 텍스트를 덧붙이고, 추가 전과 추가 후의 파일 내용을 화면에 출력합니다.

이 스크립트를 실행하면 우선 추가 전의 파일 내용을 보여주고, 새로운 한 줄을 추가한 뒤 파일의 변경된 내용을 확인시켜 줍니다.

26. 파일 존재 여부 확인

-e 옵션은 파일이나 디렉터리의 존재 여부를 검사하며, -f 옵션은 해당 이름의 항목이 일반 파일인지 확인합니다. 다음 file_exist.sh 스크립트는 명령행 인자로 전달된 파일 이름이 현재 디렉터리에 존재하는지 검사한 후 결과를 출력합니다.

예를 들어, 현재 디렉터리에 book.txt 파일이 있는 상태에서 $ zsh file_exist.sh book.txt를 실행하면 File exists라는 메시지가 출력됩니다. 반면 존재하지 않는 파일 이름, 예를 들어 book2.txt를 인자로 주어 실행하면 File does not exist라는 메시지가 출력됩니다.

27. 이메일 보내기

리눅스에서 mail이나 sendmail 같은 도구를 사용하면 스크립트로 이메일을 보낼 수 있습니다. 이를 사용하려면 시스템에 해당 패키지가 설치되어 있고 메일 서버 설정이 되어 있어야 합니다. 다음 mail_example.sh 스크립트는 간단한 예로, 미리 지정한 수신인에게 제목과 메시지를 담은 이메일을 보내는 방법을 보여줍니다.

메일 환경이 갖추어진 경우, 이 스크립트를 실행하면 admin@example.com 주소로 제목이 “Greeting”이고 내용이 “Welcome to our site”인 이메일이 전송됩니다.

28. 현재 날짜와 시간 다루기

date 명령을 사용하여 시스템의 현재 날짜와 시간을 가져올 수 있으며, 다양한 포맷 옵션을 제공하고 있습니다. 예를 들어 %Y는 연도(4자리 년도), %m는 월(2자리), %d는 일(2자리), %H는 시(시간, 24시간제), %M는 분, %S는 초를 의미합니다. 다음 date_parse.sh 스크립트에서는 이러한 옵션을 사용하여 현재 날짜와 시간을 연-월-일 및 시:분:초 형식으로 출력합니다.

이 스크립트를 실행하면 먼저 현재 시스템 날짜와 시간이 하나의 문자열로 출력되고, 이어서 Current Date is: 일-월-년 형식과 Current Time is: 시:분:초 형식으로 날짜와 시간이 각각 표시됩니다.

29. wait 명령

wait는 스크립트에서 생성된 백그라운드 프로세스가 종료될 때까지 실행을 일시 정지시키는 내장 명령어입니다. wait [PID] 형태로 특정 프로세스 ID를 지정하면 그 프로세스가 끝날 때까지 기다리고, 인자를 생략하면 현재 스크립트에서 실행한 모든 백그라운드 작업이 완료될 때까지 대기합니다.

다음 wait_example.sh 스크립트에서는 간단한 사용 예를 보여줍니다.

위 스크립트에서는 echo "Wait command" 명령을 백그라운드로 실행한 뒤, wait를 통해 해당 프로세스($process_id)가 종료될 때까지 기다립니다. 그 후 $?로 백그라운드 프로세스의 종료 상태 코드를 출력합니다.

30. 일정 시간 지연하기 (sleep)

sleep 명령을 사용하면 일정 시간 동안 스크립트 실행을 멈출 수 있습니다. 초 단위(s)는 물론, m(분), h(시간), d(일)와 같이 지연 단위를 지정할 수도 있습니다. 다음 sleep_example.sh 스크립트는 5초 동안 대기하는 예제를 보여줍니다.

이 스크립트를 실행하면 먼저 Wait for 5 seconds라는 메시지를 출력하고 약 5초간 대기한 후에 Completed라는 메시지를 출력합니다.

이상으로, 자주 사용되는 Zsh 스크립팅 기초 예제 30가지를 살펴보았습니다. 간단한 예제를 직접 실행해 보면서 Zsh 셸 스크립트의 작동 방식을 익히면, 필요에 따라 보다 복잡한 작업도 스크립트로 자동화할 수 있을 것입니다.

References

  • BASH Programming 30 Bash Script Examples by Fahmida Yesmin (https://linuxhint.com/30_bash_script_examples/)