본문으로 바로가기
TaeyoungKim.dev

Bash while read 마지막 줄 누락: IFS와 -r을 함께 쓰는 이유

리눅스작성 약 3분 읽기TaeyoungKim
LinkedInX

설정 목록을 한 줄씩 읽는 스크립트를 만들었다. 화면에는 두 줄이 보이는데 마지막 항목만 처리되지 않는다. 파일의 마지막 줄에 개행 문자가 없으면 read가 그 내용을 변수에 담고도 성공 상태로 끝나지 않기 때문이다. while 조건에서 그 상태만 검사하면 마지막 내용을 버린다.

마지막 줄에 개행이 없으면 어떤 일이 생길까?

도식의 종료 경로에서는 read가 실패 상태를 반환해도 변수에 남은 문자가 있으면 마지막 줄을 한 번 더 처리한다. IFS=와 -r은 그 과정에서 앞뒤 공백과 역슬래시를 원문대로 지키는 역할이다.

먼저 파일을 만들지 않고 입력 두 줄을 흘려보내 보자. printf의 마지막 last 뒤에는 \n이 없다.

bash
printf '  first  \nlast' | while read line; do
  printf '<%s>\n' "$line"
done
text
<first>

첫 줄 앞뒤의 공백도 사라지고 마지막 줄도 나오지 않는다. 공백은 read가 기본 IFS를 기준으로 앞뒤를 다루기 때문이고, 마지막 줄은 개행 없이 파일 끝에 도달한 read의 종료 상태 때문이다. 한 번에 두 현상이 겹치면 ‘입력이 잘렸나?’ 하고 헷갈리기 쉽다.

IFS= read -r와 남은 내용 확인을 묶는다

같은 입력에 두 가지 보존 장치를 추가한다. IFS=는 앞뒤 공백을 그대로 두고, -r은 역슬래시를 이스케이프 문자처럼 해석하지 않게 한다. read가 파일 끝 상태를 돌려줘도 변수에 내용이 남아 있으면 마지막 한 번을 처리한다.

bash
printf '  first  \nlast' | while IFS= read -r line || [ -n "$line" ]; do
  printf '<%s>\n' "$line"
done
text
<  first  >
<last>

[ -n "$line" ]은 “비어 있지 않은 내용이 남았나”를 확인한다. 파일이 정상적인 개행으로 끝났다면 read가 각 줄을 이미 처리했고, 파일 끝에서 변수는 비어 반복이 끝난다. 개행 없는 마지막 줄에는 내용이 남아 한 번 더 처리된다. 같은 구문을 빈 입력과 마지막 줄에 개행이 있는 입력에도 적용해 중복 출력이 없는지 테스트하자.

역슬래시가 들어오는 입력이라면

문자열에 \가 포함될 수 있으면 -r이 특히 중요하다. 기본 read는 역슬래시를 특별하게 취급하므로 입력을 있는 그대로 읽고 싶다는 요구와 어긋날 수 있다. 화면에서 차이를 확인하려면 printf '%s\n' 'a\b'를 두 루프에 각각 넣고 출력된 문자를 비교하면 된다.

파이프로 읽은 뒤 바깥 변수는 왜 안 바뀔까?

위 예제는 출력 결과를 보여 주기 위해 printf ... | while ...을 썼다. Bash에서는 이런 파이프의 while 부분이 별도 셸 환경에서 실행될 수 있으므로, 루프 안에서 올린 카운터를 루프 밖에서 그대로 읽을 수 있다고 가정하면 안 된다. 실제 파일을 읽으며 바깥 변수도 사용해야 한다면 아래처럼 리다이렉션으로 입력을 연결한다.

bash
count=0
while IFS= read -r line || [ -n "$line" ]; do
  count=$((count + 1))
done < items.txt
printf 'processed=%s\n' "$count"

단, 이 방식은 어디까지나 줄 단위의 일반 텍스트를 다룬다. 따옴표 안에 개행이나 쉼표가 들어갈 수 있는 진짜 CSV를 IFS만으로 올바르게 해석할 수는 없다. 그런 입력은 CSV 파서를 사용해야 한다. 파일 경로는 실제로 읽을 파일로 바꾸고, 한 번에 시스템 전체 파일에 적용하지 말고 작은 샘플로 먼저 확인하자.

핵심 요약: 입력의 끝과 내용 보존을 따로 확인한다

while read에서 마지막 줄이 빠지면 개행 유무를 확인한다. IFS= read -r line || [ -n "$line" ]은 공백·역슬래시와 개행 없는 마지막 줄을 함께 보존한다. 파이프로 읽은 뒤 루프 밖 상태를 사용할 때는 별도 셸 환경도 점검하자.

작성자

TaeyoungKim

기초 개념을 구현과 검증, 실제 운영 판단까지 연결해 기록합니다.

#Bash#while read#IFS#파일 읽기#마지막 줄

함께 읽으면 좋은 글