터미널에서 반복해서 명령을 실행할 때, 매번 긴 명령어를 치기보다 숫자 하나로 메뉴를 골라 실행하는 방식을 쓰면 편하다. 예를 들어 개발 중에 디렉터리 목록을 ls, ls -al, ls -a 등으로 자주 바꿔 보는 경우, 숫자 1·2·3만 입력해 선택할 수 있게 하면 효율이 올라간다. 이 글에서는 Bash에서 숫자를 입력받아 해당 명령을 실행하는 반복 메뉴 셸 스크립트를 만드는 방법을 다룬다. while 루프와 case 문을 이용한 패턴, 화면 정리·입력·종료 처리, 그리고 메뉴를 늘리거나 실무에서 쓸 때의 주의점까지 정리한다.
왜 숫자 메뉴인가
긴 옵션이 붙은 명령을 자주 바꿔 가며 쓸 때, 숫자 한두 자리로 선택할 수 있으면 타이핑이 줄고 실수가 줄어든다. 스크립트로 묶어 두면 **동일한 작업을 여러 환경(서버·로컬·CI)**에서 같은 방식으로 실행할 수 있고, 팀원에게 “1번 메뉴 실행해줘"처럼 지시하기도 쉽다. 따라서 반복 메뉴(메뉴 표시 → 입력 받기 → 분기 실행 → 다시 메뉴) 구조를 한 번 익혀 두면, 단순한 운영·자동화 스크립트를 빠르게 설계할 수 있다.
핵심 구조: while + case
Bash에서 이런 반복 메뉴를 만들 때 쓰는 전형적인 구조는 두 가지다. 첫째, 무한 루프로 메뉴를 계속 보여 주고 입력을 받는 while true (또는 while :) 구문이다. 둘째, 입력값에 따라 실행할 명령을 나누는 case … esac 다중 분기다. 이 둘을 묶으면 “메뉴 출력 → 사용자 입력 → case로 분기 → 명령 실행 → (종료가 아니면) 다시 메뉴” 흐름이 완성된다. exit으로 스크립트를 끝내는 선택지(예: q)를 하나 두면, 무한 루프에서 안전하게 빠져나올 수 있다.
전체 예제 코드
아래 스크립트는 메뉴에서 1이면 ls, 2면 ls -al, 3이면 ls -a를 실행하고, q를 입력하면 스크립트를 종료한다. 매번 메뉴를 보여 주기 위해 루프 시작 시 clear로 화면을 지우고, read로 한 줄 입력을 받은 뒤 case로 분기한다.
| |
- clear: 매 반복마다 화면을 비워 메뉴만 보이게 한다. (원문의
clean은 일반 셸 명령이 아니며, 화면 지우기는 clear를 사용한다.) - read -r no: 한 줄을 읽어 변수
no에 넣는다.-r은 백슬래시 이스케이프를 해석하지 않도록 해서 입력을 그대로 받는다. - case $no in … esac:
no값이1,2,3,q일 때 각각 다른 명령을 실행하고, 그 외(*)는 “Invalid option.“을 출력한다. - exit 0:
q선택 시 종료 코드 0으로 스크립트를 끝낸다. - 마지막 read -r: 결과를 읽을 시간을 주고, Enter로 다음 메뉴로 넘어가게 할 수 있다(선택 사항).
실행 흐름 다이어그램
메뉴 표시 → 입력 → 분기 → (종료 또는 반복) 흐름은 아래와 같다.
flowchart TD Start([시작]) ShowMenu["메뉴 출력clear 후 1,2,3,q 표시"] ReadInput["read로 번호/문자 입력"] Case1["1: ls 실행"] Case2["2: ls -al 실행"] Case3["3: ls -a 실행"] Quit["q: exit 0"] Invalid["그 외: Invalid option 출력"] LoopBack(다시 메뉴로) ScriptEnd([종료]) Start --> ShowMenu ShowMenu --> ReadInput ReadInput --> Case1 ReadInput --> Case2 ReadInput --> Case3 ReadInput --> Quit ReadInput --> Invalid Case1 --> LoopBack Case2 --> LoopBack Case3 --> LoopBack Invalid --> LoopBack LoopBack --> ShowMenu Quit --> ScriptEnd
노드 ID는 camelCase/PascalCase로만 쓰고, 라벨에 콜론·공백이 있어도 Mermaid 문법을 위해 노드 텍스트는 짧게 두었다. “1: ls 실행"처럼 콜론·등호가 들어가는 설명이 필요하면 해당 노드 라벨을 큰따옴표로 감싼 형태(예: Case1["1: ls 실행"])를 사용하면 된다.
메뉴 확장과 종료·에러 처리
메뉴를 늘리려면 case에 패턴과 실행할 명령을 추가하면 된다. 숫자뿐 아니라 문자(예: a, b)나 복수 문자도 패턴으로 쓸 수 있다. 종료는 q 하나가 아니라 q|Q|exit처럼 여러 패턴을 |로 묶어 줄 수 있다.
입력이 비어 있거나 숫자/문자 외 값이 들어오는 경우, 위 예제에서는 *) 브랜치에서 “Invalid option.“을 출력하고 다시 메뉴로 돌아가므로, 최소한의 에러 처리가 들어가 있다. 실무에서는 입력 검증(예: 숫자만 허용, 빈 입력 재입력 유도)을 더 넣으면 스크립트가 견고해진다.
언제 쓰고 언제 피할지
- 쓸 만한 경우: 동일한 몇 가지 명령을 반복해 실행할 때, 터미널에서 간단한 메뉴로 선택하고 싶을 때, 옵션이 다른 명령들을 한 스크립트로 통합해 팀에서 공유할 때.
- 피하는 편이 나은 경우: 메뉴가 매우 많아지면(예: 20개 이상) case 문이 비대해지고 유지보수가 어려우므로, 그때는 번호 대신 **선택 목록(select)**이나 다이얼로그(whiptail/dialog) 등 다른 UI를 고려하는 것이 좋다. 또한 비대화형 자동화(CI, cron)에서는 사용자 입력이 없으므로 이 패턴 대신 인자·환경 변수로 분기하는 방식이 맞다.
핵심 요약
| 항목 | 내용 |
|---|---|
| 반복 구조 | while true로 무한 루프, 매 턴에 clear 후 메뉴 출력 |
| 입력 | read -r no로 한 줄 입력, case $no in으로 분기 |
| 종료 | q 등 한 패턴에서 exit 0 호출 |
| 확장 | case에 패턴과 명령 추가, q|Q처럼 여러 패턴 가능 |
| 주의 | clean이 아니라 clear, read는 -r 권장, 비대화형 자동화에는 부적합 |
이 글을 읽은 뒤에는 while true + case로 숫자/문자 메뉴를 만드는 방법을 설명할 수 있고, 주어진 메뉴에 항목을 추가하거나 종료·에러 처리 방식을 바꿀 수 있으며, “대화형 메뉴"와 “인자 기반 자동화” 중 어떤 상황에 이 패턴을 쓸지 구분할 수 있다.
![Featured image of post [Shell] 숫자로 메뉴 실행하는 셸 스크립트 예제](/post/2021-05-17-shell-script-number-example/wordcloud_hu_26b01c0f59740ae9.webp)
![[Hardware] LattePanda Alpha에 Ubuntu 16.04 LTS 설치 가이드](/post/2018-12-06-install-ubuntu-16.04-on-lattepanda/wordcloud_hu_fc536f8de2cbd4bf.webp)
![[RPM] Spec 파일에서 주석과 매크로 동시 사용 시 주의사항](/post/2021-11-24-rpm-spec-comments/wordcloud_hu_6d09ac09623081c7.webp)
![[Plex] Windows에서 Plex Media Server 재실행·자동 재시작 가이드](/post/2023-01-13-restart-plex-media-server/wordcloud_hu_ba5ac3c6f7684b1d.webp)
![[Tutorial] Learn Prompting - 프롬프트 엔지니어링 무료 가이드 정리](/post/2022-12-30-learn-prompting/wordcloud_hu_6a9d105de4834753.webp)
![[How-To] Windows 10 다중 사용자 카카오톡 실행 권한 부여](/post/2021-04-07-window10-multiuser-kakaotalk/wordcloud_hu_5fcf6a8683d09a52.webp)