리눅스 split 명령어 사용법 - 대용량 파일을 줄·크기 단위로 쪼개고 다시 합치기
이 명령어를 언제 쓰는가
한 덩어리로는 다룰 수 없는 파일을 쪼갤 때 쓴다. 20GB 짜리 DB 덤프를 전송 제한에 맞춰 자르거나, 500만 줄 로그를 병렬로 처리하려고 CPU 코어 수만큼 나누거나, 편집기가 열지 못하는 크기의 파일을 잘라서 들여다보는 경우다.
중요한 성질은 split 이 원본을 건드리지 않는다는 것이다. 조각을 새로 만들 뿐이라 디스크 여유 공간이 원본 크기만큼 더 필요하다. 이 점을 잊고 이미 꽉 찬 디스크에서 실행해 서비스를 멈추는 사고가 종종 난다.
기본 형식
split [옵션] [입력파일] [접두사]
- 접두사를 생략하면
x다. 결과는xaa,xab,xac... 로 만들어진다. - 입력 파일을 생략하거나
-로 주면 표준 입력을 읽는다. 파이프 뒤에 붙일 수 있다. - 옵션을 아무것도 주지 않으면 1000줄씩 자른다.
조각 이름이 알파벳 순으로 만들어지기 때문에 cat 접두사* > 원본 으로 원래 순서대로 복원된다. 이것이 split 의 설계 의도다.
자주 쓰는 옵션
| 옵션 | 의미 | 예시 |
|---|---|---|
-l N | N줄씩 자른다. 텍스트라면 대부분 이것 | split -l 100000 app.log part_ |
-b SIZE | SIZE 바이트씩 자른다. K M G 접미사를 붙일 수 있다 | split -b 100M dump.sql chunk_ |
-d | 접미사를 알파벳 대신 숫자(00, 01, ...)로 | split -d -l 5000 a.csv p_ |
-a N | 접미사 길이. 기본 2글자 | split -a 4 -l 100 a.log p_ |
-n N | N개 조각으로 나눈다 | split -n 8 big.txt part_ |
-p 정규식 | 패턴에 맞는 줄에서 자른다 (BSD 전용) | split -p '^--- ' report.txt sec_ |
--additional-suffix=S | 조각 이름 뒤에 확장자를 붙인다 (GNU 전용) | split -l 1000 --additional-suffix=.csv a.csv p_ |
GNU 와 BSD 차이가 큰 명령이다. --additional-suffix, --filter, -C(줄을 깨지 않는 최대 크기) 는 GNU 전용이고, -p 정규식 은 BSD 전용이다.
실전 예제
1) 큰 로그를 10만 줄씩 잘라 병렬로 돌린다. 조각마다 별도 프로세스로 파싱할 때 쓴다.
split -l 100000 access.log part_
part_aa, part_ab ... 순서로 만들어진다. 이어서 xargs 로 병렬 처리한다.
ls part_* | xargs -P 4 -I{} sh -c 'awk "{print \$1}" {} | sort -u > {}.ip'
2) DB 덤프를 100MB 단위로 잘라 전송한다. 업로드 크기 제한이 있는 스토리지에 올릴 때 쓴다.
split -b 100M dump.sql dump.sql.part_
scp dump.sql.part_* backup@10.0.0.20:/srv/backup/
받는 쪽에서는 이렇게 복원한다.
cat dump.sql.part_* > dump.sql
sha256sum dump.sql
합친 뒤 원본과 체크섬을 비교하는 것까지가 한 세트다. macOS 라면 shasum -a 256 dump.sql 이다.
3) CSV 를 헤더를 유지한 채 나눈다. split 은 헤더를 알아서 복사하지 않으므로 직접 붙여 준다.
head -n 1 data.csv > /tmp/header.csv
tail -n +2 data.csv | split -l 50000 - /tmp/chunk_
for f in /tmp/chunk_*; do cat /tmp/header.csv "$f" > "$f.csv"; rm "$f"; done
4) 코어 수만큼 조각을 낸다. 조각 수를 미리 정하고 싶을 때 쓴다.
split -n $(nproc) big.txt part_
macOS 에는 nproc 이 없으므로 sysctl -n hw.ncpu 를 쓴다. 주의할 점은 -n 이 바이트 기준이라 줄 중간에서 잘린다는 것이다. 줄을 보존하려면 GNU 의 -n l/8 형식을 써야 한다.
split -n l/8 big.txt part_
5) 압축 파일을 풀지 않고 조각 낸다. 중간 파일 없이 파이프로 처리한다.
zcat access.log.gz | split -l 200000 -d -a 3 - /var/tmp/acc_
함정과 주의점
기본 접미사 2글자로는 676개까지밖에 못 만든다. aa 부터 zz 까지다. 그 이상 필요하면 BSD split 은 split: too many files 로 멈춘다. 이미 만들어진 676개 조각은 남아 있고 나머지는 사라지므로, 그 상태에서 cat 으로 합치면 잘린 데이터가 된다. 조각이 많을 것 같으면 처음부터 -a 4 를 준다.
$ seq 1 700 > big.txt
$ split -l 1 big.txt p_
split: too many files
$ ls p_* | wc -l
676
-b 는 줄 한가운데서 자른다. 바이너리나 최종적으로 다시 합칠 파일이면 상관없지만, 조각을 하나씩 열어 보거나 개별로 파싱할 계획이라면 -l 을 써야 한다. 한글이 들어간 텍스트를 -b 로 자르면 조각 경계에서 글자가 깨진다.
기본적으로 기존 조각 파일을 덮어쓴다. 같은 디렉터리에서 접두사를 그대로 두고 다시 실행하면, 이번에 조각이 더 적게 나왔을 때 이전 실행의 남은 조각이 그대로 섞인다. 나중에 cat p_* 하면 정체 모를 데이터가 뒤에 붙는다. 조각은 항상 빈 디렉터리에 만들고, 재실행 전에 지운다.
디스크 여유를 먼저 확인한다. split 은 복사이지 이동이 아니다. 20GB 파일을 쪼개면 순간적으로 40GB 가 필요하다. df -h 로 확인하고 시작한다.
함께 보면 좋은 명령어
cat— 조각을 원래 순서대로 다시 합치는 짝이다.csplit— 줄 수가 아니라 패턴 경계로 나눌 때 GNU 환경의 표준 도구다.xargs— 나눈 조각들을-P로 병렬 처리할 때 이어서 쓴다.