2016년 2월 11일 목요일

[LINUX shell script programming] basename을 써야하는 이유

Next-generation sequencing 결과파일을 일괄적으로 처리하기 위해 요즘 bash script를 종종 작성하고 있다. 명령행 인수로 공급한 파일명으로부터 출력파일에 사용할 문자열을 추출하기 위한 가장 능률적인 방법이 무엇인지 공부하는 중이다. 가령 다음과 같은 스크립트를 실행한다고 가정하자.
$ my_script.sh file_1.fastq.gz file_2.fastq.gz
입력 인수로부터 "file"이라는 문자열을 추출하여 출력 파일명인 file.ec.fastq를 완성해야 한다고 가정하자. 이는 bash가 기본적으로 제공하는 삭제 또는 치환 기능을 사용하면 된다. 처첫번째 명령행 인수를 저장하는 $1 변수를 이용하여 원하는 문자열을 추출, BASE 변수에 저장해 보자.
BASE=${1%_*}
 이렇게 실행하면 $1 변수(file_1.fastq.gz)의 뒤로부터 '_*', 즉 _로 시작하고 어떤 길이의 어떤 문자(열) 전체에 해당하는 부분을 제거한 뒤 남은 부분을 BASE 변수에 저장한다. %는 가장 짧은 매치, %%는 가장 긴 매치이다. 다시 말하자면 $1=test_trial_1.fastq.gz인 상황에서 test만 뽑아내려면 BASE=${1%%_*}라고 하면 된다.

# 또는 ##는 다른 의미를 갖는다. 변수 $1의 앞부분부터 탐색하여 매치가 되는 부분까지를 제거하는 것이다. 삭제가 아니라 치환을 원한다면 ${string/substring/replacement}의 형식을 취하면 된다. 좀 더 상세한 내용을 원한다면 Advanced Bash-scripting Guide의 10.1 Manipulating Strings 항목을 참조하라.

그런데 작업하려는 파일이 만약 다른 디렉토리에 있다면 어떻게 될까? 다음과 같이 명령행을 쳐야 하는 상황이라 가정해 보자.
$ my_script.sh ../file_1.fastq.gz ../file_2.fastq.gz
앞서 설명한 방식으로는 BASE 변수에 ../file이 저장될 것이다. 앞부분의 '../'를 제거하려면 탐색 및 삭제 작업을 한번 더 실행해야 한다.  basename 유틸리티는 파일명으로부터 디렉토리와 suffix를 제거함으로써 파일명을 반환하며, %나 #을 사용한 문자열 조작보다는 이해하기가 좀 더 쉽다. 상황에 맞는 적절한 스크립트 작성 기법이 필요한 순간이다.

댓글 없음: