FASTQ와 표 파일, 열어 보지 않고 명령어로 확인할 수 있을까요? 분석가를 위한 리눅스 명령줄 기본기

📌 이 글에서 알 수 있는 것

  • 분석가가 GUI 대신 명령줄을 쓰는 이유
  • 압축 FASTQ·TSV를 열지 않고 보고, 세고, 뽑는 기본 명령 20여 개
  • 파이프·리디렉션, awk·sed 한 줄 명령, 여러 시료 일괄 처리
  • 데이터를 지우거나 망가뜨리지 않는 안전 습관

🖥️ 왜 명령줄인가요?

오믹스 파일은 크고 많습니다. 시료 하나의 FASTQ가 수 GB이고, 분석 서버(HPC)는 보통 화면 없이 터미널로만 접속합니다. 스프레드시트에는 다른 위험도 있습니다. PubMed Central 논문의 보충 파일을 조사한 2021년 연구에서, 엑셀 유전자 목록이 있는 논문 11,117편 중 3,436편(30.9%)에서 유전자 이름이 날짜·숫자로 바뀐 오류가 발견됐습니다1.

명령줄은 원본을 건드리지 않고 읽고, 쓴 명령 자체가 처리 기록으로 남습니다. 2026년 생물학자용 Unix 교육과정도 less·head·gzip·wc·grep·cut을 3단계, 파이프·리디렉션·sort를 4단계 핵심 기술로 묶었습니다2. 이 글의 예시는 GNU 도구(리눅스 서버 기본) 기준입니다.

명령줄 파이프 흐름도. sample.fastq.gz를 gzip -cd로 풀고 파이프로 awk가 서열 줄 길이를 출력하고 sort -n과 uniq -c로 개수를 세어 lengths.txt로 저장한다. gzip의 오류 메시지는 표준 오류 통로로 err.log에 따로 저장된다. 아래에 파이프와 리디렉션 기호 네 가지의 뜻이 정리돼 있다.
그림 1. 작은 명령을 파이프로 잇는 방식과 리디렉션 기호.

📂 둘러보기와 열어 보기

ls -lh raw/
pwd
less -S sample_sheet.tsv
head -n 8 sample.fastq
tail -n +2 sample_sheet.tsv
  • ls -l: 권한·크기·날짜를 길게 표시, -h: 크기를 K·M·G 단위로
  • pwd: 지금 위치. 이 글의 명령은 모두 raw/와 results/가 있는 프로젝트 폴더에서 실행합니다(이동은 cd 폴더, cd ..은 한 단계 위, cd ~는 홈)
  • less -S: 긴 줄을 접지 않고 잘라 표처럼 보기, 좌우 화살표로 이동, q로 종료
  • head -n 8: 앞 8줄(FASTQ 2리드), tail -n +2: 2번째 줄부터 출력(머리글 빼기)3
  • 자주 하는 실수: 큰 파일을 cat으로 열어 터미널이 멈춤. 먼저 head나 less로 봅니다.

모르는 옵션은 man sort나 sort --help로 그 자리에서 확인합니다.

압축 파일은 풀어서 저장하지 않고 흐름으로 읽습니다.

gzip -cd sample.fastq.gz | head -n 8
zless sample.fastq.gz
pigz -k -p 8 sample.fastq
  • gzip -c: 결과를 표준 출력(화면으로 나가는 기본 출력)으로 보내고 원본 유지, -d: 압축 해제. zcat은 gunzip -c와 같습니다4
  • zless: 압축 파일을 그대로 화면 단위로 보기
  • pigz -p 8: 8개 스레드로 gzip 형식 압축. gzip처럼 끝나면 원본을 지우므로 원본을 남기려면 -k를 붙입니다. 해제는 병렬화되지 않습니다5
  • 자주 하는 실수: macOS 기본 zcat은 .Z 파일을 찾아 .gz에서 실패할 수 있습니다. gzip -cd를 쓰면 어디서나 됩니다.

🔗 파이프와 리디렉션

gzip -cd sample.fastq.gz 2> err.log | wc -l > lines.txt
echo "sample2 done" >> run.log
  • |: 앞 명령의 출력을 다음 명령의 입력으로
  • >: 파일로 저장(이미 있으면 덮어씀), >>: 끝에 덧붙이기
  • 2>: 오류 메시지(표준 오류)만 따로 저장6
  • 자주 하는 실수: 입력 파일로 바로 다시 저장(sort a.tsv > a.tsv). 셸이 먼저 파일을 비워 내용이 사라집니다.
  • 자주 하는 실수: 2>는 바로 앞 명령 하나에만 붙습니다. 파이프 끝에 붙이면 앞 명령(gzip)의 오류는 저장되지 않습니다.

🧰 텍스트 도구 다섯 가지

grep -c -w "TP53" genes.tsv
grep -v "^#" variants.vcf | head
cut -f 1,3 genes.tsv
tail -n +2 genes.tsv | sort -t $'\t' -k4,4n
cut -f 3 genes.tsv | sort | uniq -c
wc -l genes.tsv
  • grep -c: 일치하는 줄 수, -w: 단어 전체가 일치할 때만(TP53BP1은 빠지지만 하이픈이 붙은 TP53-AS1은 걸림. 열 값이 정확히 같은 줄은 awk -F '\t' '$2 == "TP53"'), -v: 일치하지 않는 줄(여기서는 # 머리글 빼기)7
  • cut -f: 열 번호로 뽑기. 기본 구분자가 TAB이라 TSV에 바로 쓰고, CSV는 -d ','
  • sort -k4,4: 4번째 열만 기준. -k4만 쓰면 4번째 열부터 줄 끝까지가 기준입니다. -n: 숫자 크기순(1e-10 같은 지수 표기는 -g), -t $'\t': TAB 구분(기본은 공백 경계라 값에 공백이 있으면 열이 밀림)
  • uniq -c: 연속된 같은 줄을 개수와 함께 하나로. 붙어 있는 줄만 합치므로 반드시 sort 뒤에3
  • wc -l: 줄 수(머리글 포함)
  • 자주 하는 실수: sort 순서는 로케일(언어 설정)에 따라 달라집니다. 파일끼리 비교할 정렬은 LC_ALL=C sort로 고정합니다.

🧮 실전 한 줄 명령

FASTQ는 리드 하나가 4줄입니다. head -n 4로 보면 구조가 보입니다.

@read1 1:N:0:ACGT
GATTACAGATTACA
+
IIIIIHHHGG@@?#
  • 1줄: @로 시작하는 리드 이름, 2줄: 서열, 3줄: + 구분 줄, 4줄: 염기별 품질 점수(문자 하나가 염기 하나)

그래서 리드 수는 줄 수를 4로 나눕니다.

echo $(( $(gzip -cd sample.fastq.gz | wc -l) / 4 ))
  • 예를 들어 출력이 2500000이면 리드 250만 개. paired-end면 R1·R2가 같아야 합니다.
  • 자주 하는 실수: grep -c '^@'로 세기. 품질 줄도 @로 시작할 수 있어, 리드 2개짜리 파일에서 3이 나오기도 합니다.

TSV에서 열 하나를 뽑아 범주별로 셉니다.

tail -n +2 genes.tsv | cut -f 3 | sort | uniq -c | sort -k1,1nr
  • 머리글을 빼고 3번째 열(예: biotype)을 뽑아 범주별 개수를 많은 순으로 보여 줍니다. 예를 들어 출력이 19000 protein_coding이면 그 범주가 1만 9천 줄이라는 뜻입니다.
  • -k1,1nr: 첫 열을 숫자 역순(r)으로

✂️ awk와 sed는 짧게

awk -F '\t' 'NR > 1 && $5 >= 30 {print $1}' table.tsv
awk -F '\t' 'NR > 1 {s += $2} END {print s}' counts.tsv
gzip -cd sample.fastq.gz | awk 'NR % 4 == 2 {print length($0)}' | sort -n | uniq -c
sed 's/^chr//' regions.bed
sed -n '1,4p' sample.fastq
  • -F '\t': TAB으로 열을 나눔, $1: 첫 열, NR: 지금까지 읽은 줄 번호, END: 다 읽은 뒤 실행8
  • 첫 줄: 머리글 제외, 5열이 30 이상인 줄의 1열 출력 / 둘째 줄: 2열 합계 / 셋째 줄: 리드 길이 분포
  • s/찾을것/바꿀것/: 줄마다 처음 일치한 것을 치환(전부는 끝에 g), -n ... p: 지정한 줄만 출력9
  • 자주 하는 실수: 값이 NA인 칸은 문자열 비교가 돼 조건을 통과합니다. $5+0 >= 30처럼 숫자로 바꿔 비교합니다.
  • 자주 하는 실수: sed -i(macOS는 sed -i '')로 원본을 바로 고치기. 새 파일로 저장해 확인한 뒤 바꿉니다.

🔁 여러 시료를 한 번에

for fq in raw/*_R1.fastq.gz; do
  s=$(basename "$fq" _R1.fastq.gz)
  printf '%s\t%s\n' "$s" $(( $(gzip -cd "$fq" | wc -l) / 4 ))
done > read_counts.tsv
  • basename: 경로와 꼬리(_R1.fastq.gz)를 떼어 시료 이름만 남김
  • printf '%s\t%s\n': 시료 이름과 리드 수를 TAB으로 이어 한 줄씩 출력. 결과는 시료별 리드 수 표
  • 자주 하는 실수: 일치하는 파일이 없으면 패턴 문자열이 그대로 들어가 표에 *와 0으로 된 가짜 행이 남습니다(종료 상태 0). 루프 앞에 shopt -s nullglob을 둡니다.
  • 자주 하는 실수: 손상된 .gz도 잘린 리드 수가 그대로 표에 들어가고, set -euo pipefail로도 멈추지 않습니다. 아래 gzip -t 검사를 먼저 돌립니다.
find raw -name '*.fastq.gz' -print0 | xargs -0 -n 1 -P 4 gzip -t
parallel -j 4 'gzip -cd {} | wc -l > results/{/.}.lines' ::: raw/*.fastq.gz
  • xargs -P 4: 동시에 4개 실행(기본 1), -n 1: 한 번에 파일 하나, -0: -print0과 짝지어 공백 있는 이름도 안전하게10
  • gzip -t: 압축 파일 손상 검사(정상이면 아무것도 출력하지 않음)
  • parallel -j 4: 작업 4개 동시, {}: 입력 파일, {/.}: 경로와 마지막 확장자를 뗀 이름(결과는 results/에 저장, 먼저 mkdir -p results), ::: 뒤가 입력 목록
  • 논문 방법에 GNU parallel을 쓰면 parallel --citation이 보여 주는 판본별 정보로 인용합니다11.
  • 자주 하는 실수: 서버 코어보다 많이 띄우거나, 여러 작업이 한 파일에 동시에 써서 출력이 섞임

🛡️ 데이터를 지키는 안전 습관

#!/usr/bin/env bash
set -euo pipefail
outdir="results"
rm -rf -- "${outdir:?}/tmp"
md5sum -c md5sums.txt
chmod -R a-w raw/
  • set -e: 명령이 실패하면 멈춤, -u: 정의되지 않은 변수를 오류로, -o pipefail: 파이프 중간 실패도 실패로6
  • 이 블록은 파일(예: check.sh)로 저장해 bash check.sh로 실행합니다. 터미널에 set -e를 직접 치면 이후 명령 하나만 실패해도 창이 닫히거나 접속이 끊깁니다.
  • "$var": 큰따옴표가 없으면 my sample.fastq.gz 같은 이름이 두 개로 쪼개집니다. 파일 이름에는 처음부터 공백을 쓰지 않는 편이 좋습니다.
  • ${outdir:?}: 변수가 비어 있으면 멈춤. 비어 있는 변수로 rm -rf "$outdir/tmp"이 돌면 /tmp를 지우려 듭니다.
  • md5sum -c: 받은 파일을 제공처의 체크섬 목록과 대조. 목록에 파일 이름만 있으면 (cd raw && md5sum -c ../md5sums.txt). gzip -t는 압축 형식만 검사합니다
  • chmod -R a-w: 원본 폴더를 모두 쓰기 금지로. 실수 방지일 뿐 백업은 아닙니다(되돌리기는 chmod -R u+w).
  • 자주 하는 실수: set -e를 믿고 확인을 생략. if 조건, && 중간 명령, 명령 인자 속 $(...)의 실패에는 멈추지 않습니다.

⚠️ 한계와 주의

  • 도구 판본 차이: macOS의 sed·zcat·cat·sort는 BSD 계열이라 옵션이 다릅니다. 예시가 안 되면 리눅스 서버에서 돌리거나 GNU 도구를 설치합니다. macOS 기본 셸은 zsh라 shopt가 없고 일치하는 파일이 없는 패턴은 바로 오류가 납니다. 예시는 bash를 실행한 뒤 따라 합니다.
  • pipefail과 head: 스크립트 안 gzip -cd 큰파일 | head는 head가 먼저 끝나면 gzip이 비정상 종료(141)로 기록돼 멈출 수 있습니다.
  • 윈도에서 만든 표: 줄 끝에 CR 문자가 붙어 마지막 열 비교가 틀어집니다. cat -A(macOS는 cat -vet)로 줄 끝의 ^M을 확인하고, tr -d '\r' < in.tsv > out.tsv로 지웁니다.
  • 복잡한 형식은 전용 도구로: BAM·VCF는 awk로 직접 파싱하지 말고 samtools·bcftools를 씁니다(7·8편). 정렬·변이 호출은 3편, 발현 분석은 12편에서 다룹니다.

🏛️ 지금 어디까지 왔나

  • 교육: 2026년 PLoS Comput Biol 논문은 생물학자를 위한 5단계 Unix 교육과정과, 브라우저 안 터미널로 설치 없이 실습하는 Sandbox.bio 튜토리얼을 공개했습니다2.
  • 한국: 국내 대학·기관의 명령줄 교육과정이나 공용 분석 서버 현황은 확인하지 못했습니다.

🧪 연구자 노트

  • 명령을 외우기보다 head, less로 파일을 먼저 열어 보는 습관이 중요합니다. 분석 오류의 상당수는 파일 형식이나 열 순서를 확인하지 않아서 생깁니다.
  • rm과 덮어쓰기(>)는 되돌릴 수 없습니다. 원본 데이터 폴더는 읽기 전용으로 두고, 결과는 다른 폴더에 쓰세요.

🙋 그래서 나에게는? — 실습 전 체크리스트

  • 원본 FASTQ를 별도 폴더에 두고 md5sum -c로 대조한 뒤 chmod -R a-w로 잠갔다
  • 리눅스 서버인지 macOS인지, GNU 도구인지 확인했다
  • 큰 파일은 head·less -S·gzip -cd ... | head로 먼저 봤다
  • 리드 수는 줄 수÷4로 세고 R1·R2를 대조했다
  • 스크립트 첫 줄에 set -euo pipefail을 넣고 변수를 큰따옴표로 감쌌다
  • 쓴 명령을 스크립트나 기록 파일로 남겼다

⚠️ 이 글은 의학적 조언이 아니며, 특정 제품을 권하지 않습니다. 실제 환경에서는 기관 서버의 사용 규칙과 SOP를 우선하세요.

❓ 자주 묻는 질문

Q. 윈도 PC만 있는데 따라 할 수 있나요? A. WSL(윈도 안의 리눅스 환경)을 쓰거나 기관 리눅스 서버에 접속하면 됩니다. 설치가 어렵다면 Sandbox.bio처럼 브라우저 안 터미널로 먼저 연습할 수 있습니다2.

Q. awk와 Python 중 무엇을 배워야 하나요? A. 열 뽑기·합계·조건 필터처럼 한 줄로 끝나는 일은 awk가 빠릅니다. 여러 단계 계산이나 통계·그림이 필요하면 Python이나 R로 넘어가는 편이 낫습니다(10편).

Q. 명령이 잘 돌았는지 어떻게 확인하나요? A. echo $?로 직전 명령의 종료 상태를 봅니다(0이면 성공). 파이프는 마지막 명령의 상태만 보여 주므로, 앞 명령까지 보려면 bash에서 echo "${PIPESTATUS[@]}"를 쓰거나 set -o pipefail을 켭니다. 오류 로그(2>로 저장한 파일)도 함께 확인합니다.

📚 오믹스 기술 시리즈

참고


  1. Abeysooriya M 외. Gene name errors: lessons not learned. PLoS Comput Biol 2021;17:e1008984. doi:10.1371/journal.pcbi.1008984 ↩︎

  2. Khamvongsa-Charbonnier L 외. Training biologists in Unix command-line skills: from curriculum to interactive online tutorials. PLoS Comput Biol 2026;22:e1014133. doi:10.1371/journal.pcbi.1014133 ↩︎ ↩︎ ↩︎

  3. GNU coreutils 9.11 매뉴얼 페이지(sort, uniq, cut, head, tail, wc; 2026-11-06 접속) — man7.org ↩︎ ↩︎

  4. GNU gzip 1.14 매뉴얼 페이지(gzip, zless; 2026-11-06 접속) — manpages.debian.org ↩︎

  5. Adler M. pigz 매뉴얼(2023-08-19판, 2026-11-06 접속) — zlib.net/pigz ↩︎

  6. GNU Bash 5.3 매뉴얼 페이지(set 내장 명령·리디렉션; 2026-11-06 접속) — man7.org ↩︎ ↩︎

  7. GNU grep 3.12 매뉴얼 페이지(2026-11-06 접속) — man7.org ↩︎

  8. GNU awk(gawk) 5.4 매뉴얼 페이지(2026-11-06 접속) — man7.org ↩︎

  9. GNU sed 4.10 매뉴얼 페이지(2026-11-06 접속) — man7.org ↩︎

  10. GNU findutils xargs 매뉴얼 페이지(2026-11-06 접속) — man7.org ↩︎

  11. GNU parallel 20261022 문서(–citation; 2026-11-06 접속) — gnu.org; Tange O. GNU Parallel 2018. Zenodo; 2018. doi:10.5281/zenodo.1146014 ↩︎