티스토리 뷰
레거시 시스템에서 넘어온 CSV 수백 개를 열었더니 한글이 전부 깨져 있었다. euc-kr(정확히는 cp949)로 저장된 파일을 utf-8 환경에서 열었을 때 나오는 전형적인 증상이다.
파일이 한두 개면 에디터로 열어서 다시 저장하면 되지만, 수백 개는 그렇게 못 한다. iconv와 셸 스크립트로 한 번에 처리한다.
기본 스크립트
#!/bin/bash
# csv 파일 목록을 가져온다
csv_files=`ls -1 *.csv`
# 변환 결과를 담을 디렉터리
mkdir -p utf8
for csv_file in $csv_files; do
iconv -c -f euc-kr -t utf-8 "$csv_file" > "utf8/$csv_file"
done
옵션 의미는 이렇다.
-f euc-kr: 원본 인코딩-t utf-8: 변환할 인코딩-c: 변환할 수 없는 문자를 버리고 계속 진행
-c 옵션은 양날의 검이다
-c가 없으면 변환 불가 문자를 만나는 순간 에러로 중단된다. 그래서 대량 처리에는 편한데, 문제가 있는 문자를 조용히 삭제한다는 게 함정이다.
데이터가 중요하다면 -c 없이 먼저 돌려서 어느 파일이 실패하는지 확인하는 편이 낫다.
for f in *.csv; do
if ! iconv -f euc-kr -t utf-8 "$f" > /dev/null 2>&1; then
echo "변환 실패: $f"
fi
done
실패 목록을 먼저 뽑고, 그 파일들만 따로 살펴본 뒤에 전체를 돌리는 순서를 권한다.
euc-kr 대신 cp949를 쓰는 게 안전하다
한국어 파일에서 자주 겪는 함정이다. 윈도우에서 만들어진 한글 파일은 대부분 cp949(= MS949, euc-kr 확장)다. euc-kr은 완성형 2,350자만 담고 있어서, 그 밖의 확장 문자가 들어 있으면 변환에 실패한다.
# euc-kr 로 실패하면 cp949 로 시도
iconv -f cp949 -t utf-8 input.csv > output.csv
실무에서는 그냥 처음부터 cp949로 지정하는 게 실패가 적다. cp949는 euc-kr의 상위 호환이라 euc-kr 파일도 문제없이 읽는다.
원본 인코딩을 모를 때
파일마다 인코딩이 섞여 있을 수도 있다. file 명령으로 추정할 수 있다.
file -I *.csv
# 또는 (리눅스)
file -bi *.csv
# 더 정확하게는 uchardet
brew install uchardet # macOS
uchardet input.csv
인코딩별로 분기 처리하는 스크립트도 만들 수 있다.
for f in *.csv; do
enc=$(uchardet "$f")
if [ "$enc" = "UTF-8" ]; then
echo "이미 UTF-8: $f"
cp "$f" "utf8/$f"
else
iconv -f "$enc" -t utf-8 "$f" > "utf8/$f"
fi
done
하위 디렉터리까지 한 번에
ls *.csv는 현재 디렉터리만 본다. 하위까지 훑으려면 find를 쓴다.
find . -name "*.csv" -type f | while read -r f; do
out="utf8/${f#./}"
mkdir -p "$(dirname "$out")"
iconv -c -f cp949 -t utf-8 "$f" > "$out"
done
파일명에 공백이 있을 수 있으니 while read -r과 큰따옴표를 반드시 쓴다. for f in $(find ...) 형태는 공백에서 깨진다.
엑셀에서 열 거라면 BOM을 붙인다
utf-8로 잘 변환했는데 엑셀에서 열면 또 깨지는 경우가 있다. 엑셀은 BOM이 없는 utf-8 CSV를 시스템 기본 인코딩으로 해석하기 때문이다.
# BOM 추가
for f in utf8/*.csv; do
printf '\xEF\xBB\xBF' | cat - "$f" > tmp && mv tmp "$f"
done
반대로 프로그램에서 파싱할 거라면 BOM이 오히려 방해가 된다. 첫 컬럼명 앞에 보이지 않는 문자가 붙어서 헤더 매칭이 실패한다. 용도에 따라 붙이거나 떼면 된다.
파일명 자체가 깨진 경우
내용이 아니라 파일명이 깨졌다면 convmv를 쓴다.
brew install convmv # macOS
# 미리보기 (실제 변경 안 함)
convmv -f cp949 -t utf-8 *.csv
# 실제 적용
convmv -f cp949 -t utf-8 --notest *.csv
맥에서는 한 가지 더 주의할 게 있다. macOS는 파일명을 NFD(자모 분리) 형태로 저장한다. "한글.csv"가 리눅스에서는 "ㅎㅏㄴㄱㅡㄹ.csv"처럼 보일 수 있다. 이 경우 -t utf-8 대신 --nfc 옵션이 필요하다.
정리
iconv -f cp949 -t utf-8이 euc-kr보다 실패가 적다-c는 변환 불가 문자를 조용히 버린다. 중요 데이터면 먼저 검증- 인코딩을 모르면
file -I또는uchardet - 하위 디렉터리는
find+while read -r, 공백 주의 - 엑셀에서 열 거면 BOM 추가, 프로그램 파싱이면 BOM 제거
- 파일명이 깨졌으면
convmv
'개발 > Etc' 카테고리의 다른 글
| 맥에서 사진 EXIF 날짜·위치 일괄 변경하기 (ExifTool) (0) | 2024.08.24 |
|---|---|
| 헷갈리는 HTML 태그 정리, em과 i는 무엇이 다른가 (0) | 2024.03.30 |
| JetBrains Translation 플러그인에 DeepL 한국어 API 기여한 이야기 (0) | 2023.11.01 |
| 맥 초반 꾸미기 (zsh, vim 을 이쁘고 편하게 쓰기) (0) | 2023.03.22 |
| 프로젝트별로 node version 자동 관리하기 (feat: nvm) (2) | 2023.03.22 |
