while과 until
for는 반복 횟수가 미리 정해졌을 때 씁니다. 반면 "조건이 참인 동안 계속해라"처럼 언제 끝날지 모를 때는 while이 적합합니다. until은 while의 반대 버전으로, 조건이 거짓인 동안 반복합니다.
while 기본 구문
while [[ 조건 ]]; do # 조건이 참인 동안 반복done
간단한 카운터 예시입니다.
count=1while [[ $count -le 5 ]]; do echo "반복 $count" ((count++))done
실행 결과는 다음과 같습니다.
반복 1
반복 2
반복 3
반복 4
반복 5
((count++))를 빠뜨리면 조건이 영원히 참이 되어 무한 루프에 빠집니다. 카운터를 반드시 증가시켜야 합니다.
무한 루프
서비스 데몬처럼 계속 실행되어야 하는 경우에는 의도적으로 무한 루프를 만듭니다.
# while true: 항상 참인 조건while true; do echo "실행 중..." sleep 1done# while :: true와 동일하지만 더 빠름while :; do echo "실행 중..." sleep 1done
:는 Bash 내장 명령어로 항상 성공(종료 코드 0)을 반환합니다. true와 동일한 역할을 하지만 별도 프로세스를 생성하지 않아 미세하게 빠릅니다. 무한 루프는 보통 내부에 break 조건을 두거나, Ctrl+C로 중단합니다.
파일 줄 단위 읽기
텍스트 파일을 한 줄씩 읽어 처리하는 가장 안전한 방법입니다.
while IFS= read -r line; do echo "줄: $line"done < /etc/hosts
IFS=는 줄 앞뒤의 공백을 보존하기 위해 필드 구분자를 빈 값으로 설정합니다. -r 옵션은 백슬래시를 이스케이프 문자로 해석하지 않고 그대로 읽습니다. 이 두 가지를 빠뜨리면 들여쓰기나 특수 문자가 있는 줄에서 원치 않는 결과가 나올 수 있습니다.
파이프를 통해서도 줄을 읽을 수 있습니다.
# 파이프로 입력받기ls -1 | while read -r line; do echo "파일: $line"done
단, 파이프 뒤의 while은 서브쉘에서 실행됩니다. 루프 안에서 설정한 변수가 루프 밖에서는 보이지 않습니다. 변수를 바깥에서 써야 한다면 리다이렉션 방식을 사용하세요.
until 구문
until은 조건이 참이 될 때까지 반복합니다. while의 NOT 버전입니다.
until [[ 조건 ]]; do # 조건이 거짓인 동안 반복done
count=0until [[ $count -ge 5 ]]; do echo "count = $count" ((count++))done
while [[ $count -lt 5 ]]와 동일한 동작입니다. "5가 될 때까지 반복"이라는 표현이 더 자연스러울 때 until을 선택합니다.
실습 1. 카운트다운 타이머 스크립트
초 단위로 카운트다운하고 완료 시 알림을 출력하는 스크립트입니다.
#!/bin/bash# 새 파일: scripts/countdown.shseconds="${1:-10}"if [[ ! $seconds =~ ^[0-9]+$ || $seconds -eq 0 ]]; then echo "사용법: $0 <초>" exit 1fiecho "카운트다운 시작: ${seconds}초"echo "-----------------------------"while [[ $seconds -gt 0 ]]; do printf "\r남은 시간: %3d초 " $seconds sleep 1 ((seconds--))doneprintf "\r \r"echo "시간이 종료되었습니다!"echo "-----------------------------"
실행 결과는 다음과 같습니다.
$ bash scripts/countdown.sh 5
카운트다운 시작: 5초
-----------------------------
남은 시간: 5초
남은 시간: 4초
남은 시간: 3초
남은 시간: 2초
남은 시간: 1초
시간이 종료되었습니다!
-----------------------------
printf "\r"은 커서를 줄의 시작으로 이동합니다. 다음 출력이 같은 줄을 덮어씌우므로 카운트가 줄어드는 효과가 납니다.
실습 2. 파일 변경 감지 대기 스크립트
특정 파일이 생성되거나 변경될 때까지 기다리는 스크립트입니다. 다른 프로세스가 파일을 만들어 주기를 기다릴 때 유용합니다.
#!/bin/bash# 새 파일: scripts/wait_for_file.shtarget="${1}"timeout="${2:-60}"if [[ -z "$target" ]]; then echo "사용법: $0 <파일경로> [타임아웃초]" exit 1fiecho "대기 중: $target (최대 ${timeout}초)"elapsed=0until [[ -f "$target" ]]; do if [[ $elapsed -ge $timeout ]]; then echo "타임아웃: ${timeout}초 동안 파일이 생성되지 않았습니다." exit 1 fi printf "\r경과: %d초 / 최대: %d초" $elapsed $timeout sleep 1 ((elapsed++))doneprintf "\r \r"echo "파일 감지됨: $target"echo "대기 시간: ${elapsed}초"
실행 결과는 다음과 같습니다.
# 터미널 1에서 실행
$ bash scripts/wait_for_file.sh /tmp/trigger.txt 30
대기 중: /tmp/trigger.txt (최대 30초)
경과: 4초 / 최대: 30초
# 터미널 2에서 파일 생성
$ touch /tmp/trigger.txt
# 터미널 1에서 자동으로 완료
파일 감지됨: /tmp/trigger.txt
대기 시간: 5초
until [[ -f "$target" ]]은 파일이 없는 동안 반복합니다. 파일이 생기면 until 조건이 참이 되어 루프를 빠져나옵니다.