2020년 2월 14일 금요일

콤마로 구분된 파일 목록을 만들기

De novo assembly를 통하여 얻은 여러 결과 파일(contig 또는 scaffold)을 한번에 비교하는 도구로서 QUAST(오, 러시아의 기술이여!)나 BBMap의 statswrapper.sh를 종종 사용한다. 소련, 즉 소비에트 연방은 요즘 더 이상 존재하는 국가는 아니지만 그 당시에 만들어진 기술이 아직도 우리집 오디오의 부속으로서 힘을 발휘하고 있다.

구 소련의 전자공학 기술로 만들어진 오디오 신호 증폭용 초단관 6N2P(6Н2П). 출처는 내 블로그. 진공관을 켜 놓고 있으면, 정말로 내가 '전자(electron)'를 부려먹고 있다는 것을 느낄 수 있다. 따라서 진공관보다는 전자관 혹은 열전자관이라고 부르는 것이 더 정확하다. 진공 자체는 중요한 조건이지만 실제 일을 하는 것은 전자니까 말이다. 진공관 표면에 찍힌 OTK라는 표식은 군용관임을 의미하는데, 이걸 볼 때마다 자꾸 한국생명공학연구원 전임 원장님이신 오태광 박사님이 떠오른다^^
매뉴얼에 의하면 QUAST는 'contig1.fa contig2.fa contig3.fa'와 같이 비교할 조립 결과물을 공백으로 구분하여 인수로 주어야 하고, statswrapper.sh는 'in=contig1.fa,contig2.fa,contig3.fa'처럼 콤마로 구분하여 공급해야 한다. 이것 때문에 작년에 생명정보학 교육을 하면서 입력 파일 목록을 만드는 짧은 스크립트를 만드는 수고를 해야만 했다. 그런데 아주 최근, 두 프로그램을 실행하면서 그냥 *.fa라고만 인수를 제공하니 멀쩡하게 잘 돌아가는 것이 아닌가. 리눅스에서 돌아가는 모든 명령어가 와일드카드를 받아먹을 수 있는 것은 아니라서 아예 시도를 해 볼 생각을 하지 않았다. 이것을 알고 난 뒤 얼마나 허탈하던지...

콤마로 구분된 파일 목록을 만들어서 인수로 제공해야 하는 다른 유틸리티도 많이 있다. 어떻게 하면 이를 좀 더 간편하게 할 수 있을까? ls -m이 바로 그런 기능을 수행한다. 하지만 콤마 뒤에 공백을 삽입하는 것이 문제이다. 이것은 없애면 된다(tr -d ' ' 이용). 그런데 여기까지만 하면 목록이 너무 길어서 한 줄을 넘어가는 경우 저절로 삽입된 줄바꿈이 드러난다. 이를 제거하기 위해 tr -d '\n'을 한번 더 실행하면 된다.

$ ls -m / | tr -d ' '
bin,boot,data,dev,etc,home,lib,lib64,lost+found,media,mnt,nas,opt,
proc,root,run,sbin,srv,sys,tmp,usr,var
$ ls -m / | tr -d ' ' | tr -d '\n'
bin,boot,data,dev,etc,home,lib,lib64,lost+found,media,mnt,nas,opt,proc,root,run,sbin,srv,sys,tmp,usr,var

대단히 간결하고도 아름답지 않은가? 실제 활용 사례를 하나 들어 보겠다. 나는 조금 전에 메타게놈 데이터를 strain 수준에서 분석하는 프로그램인 MIDAS를 실행하였다. 샘플은 13개였고, midas_sample1, midas_sample2...와 같이 개별적인 디렉토리에 결과가 수록되었다. 여기에서 만들어진 snps 분석 결과를 집계하기 위해 mergy_midas.py snps 명령을 실행하려고 한다. 전단계에서 생성한 13개의 MIDAS 결과 디렉토리를 콤마로 묶어서 인수로 제공해야 하니 다음과 같이 명령어을 내리면 된다.

앗차, 안 된다. 현 디렉토리에 여러 파일과 디렉토리가 섞인 경우 ls -m으로는 midas로 시작하는 디렉토리만을 묶을 수가 없다. ls -m midas_*는 원하는 결과가 나오지 않는다. 이렇게 하면 midas로 시작하는 디렉토리가 아니라 그 하위의 것들이 묶여서 나오는 결과를 빚는다. 내가 원하는 것은 이게 아니다.

다른 방법이 없을까? 구글을 뒤지니 'ls | grep midas | paste -s -d ',' -'가 원하는 결과를 만들어 주는 것 같았다. 좀 복잡하지만 다음의 명령이 잘 돌아가는 것을 확인하였다.

$ merge_midas.py snps outdir -i $(ls | grep midas | paste -s -d ',' -) -t list --site_depth 10

paste 명령에서 -s를 생략하면 목록이 한 줄에 출력되는 것이 아니라 저마다 new line을 달고 세로로 출력된다. paste 명령 맨 끝의 '-'는 없어도 별 상관은 없다. 오늘도 이렇게 하여 한 꺼풀의 무식함을 벗겨냈다.

댓글 없음: