리눅스에서 명령어를 입력하는 도중 TAB 키를 두 번 누르면, 입력한 문자로 시작하는 모든 사용 가능한 명령어 목록이 화면에 나타납니다.
이미 많은 분들이 알고 계신 기능일 것입니다. 이것이 바로 bash completion(Bash 자동 완성)입니다. Bash 명령줄에서는 기본적으로 파일과 디렉터리 이름 자동 완성이 제공됩니다.
하지만 complete 명령을 활용하면 이 bash 자동 완성 기능을 한 단계 더 강력하게 끌어올릴 수 있습니다.
이 글에서는 프로그래밍 가능한 자동 완성(programmable completion)을 통해 옵션과 명령어 인수까지 자동 완성을 적용하는 방법을 설명합니다.
자동 완성의 강력한 예시
예를 들어 write 명령어를 입력한 후 TAB 키를 두 번 누르면, 메시지를 보낼 수 있는 사용자 목록이 자동으로 표시됩니다.
$ write [TAB][TAB] bala raj jason randy john ritu mayla thomas nisha www-data
다음 예시에서는 telnet 명령어에 대해 접속 가능한 호스트명 목록을 보여줍니다.
$ telnet [TAB][TAB] localhost dev-db fileserver
프로그래밍 가능한 자동 완성 활성화 방법
터미널에서 프로그래밍 가능한 자동 완성을 사용하려면 아래와 같이 /etc/bash_completion 파일을 실행하기만 하면 됩니다.
# . /etc/bash_completion
또는 /etc/bash.bashrc(우분투 리눅스 13.04 기준)에서 아래 부분의 주석을 해제하면, 매번 위 명령을 직접 실행할 필요가 없습니다.
# enable bash completion in interactive shells
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
만약 해당 코드가 없거나 /etc/bash_completion 파일이 존재하지 않는다면, apt-get으로 bash-completion 패키지를 설치하면 됩니다.
1. 기존 bash-completion 설정 확인하기
프로그래밍 가능한 bash 자동 완성을 활성화하면 미리 정의된 자동 완성 규칙들이 설정되어 있습니다. bash 자동 완성은 complete 명령으로 정의합니다.
현재 시스템에 등록된 기존 자동 완성 규칙을 확인하려면 아래처럼 complete 명령을 사용하세요.
complete -p | less
위 예시에서 -p 옵션은 생략해도 무방합니다.
2. Bash의 표준 자동 완성 목록
Bash는 리눅스 사용자에게 다음과 같은 표준 자동 완성 기능을 기본으로 제공합니다.
- 변수명(variable name) 자동 완성
- 사용자명(username) 자동 완성
- 호스트명(hostname) 자동 완성
- 경로명(pathname) 자동 완성
- 파일명(filename) 자동 완성
이 내용들은 앞서 다룬 bash 표준 자동 완성 관련 글에서 자세히 설명한 바 있습니다.
3. 명령어 목록을 위한 자동 완성 정의하기
-c 옵션으로 자동 완성을 정의하면, 사용 가능한 명령어 목록이 인수로 제공됩니다. 다음 예시는 which 명령어에 대한 자동 완성을 정의한 것입니다.
$ complete -c which $ which [TAB][TAB] Display all 2116 possibilities? (y or n)
위와 같이 'y'를 입력하면 시스템의 모든 명령어가 목록으로 표시됩니다.
4. 디렉터리 목록을 위한 자동 완성 정의하기
-d 옵션을 사용하면 디렉터리 이름만 인수로 받도록 자동 완성을 정의할 수 있습니다. 다음은 ls 명령어에 대한 자동 완성을 정의한 예시입니다.
$ ls countfiles.sh dir1/ dir2/ dir3/ $ complete -d ls $ ls [TAB][TAB] dir1/ dir2/ dir3/
위와 같이 TAB 키를 누르면 디렉터리만 표시됩니다.
5. 백그라운드 작업(Job) 이름을 위한 자동 완성 정의하기
complete를 사용하면 작업(job) 이름도 명령어의 인수로 자동 완성할 수 있습니다. -j 옵션을 사용하면 작업 이름이 인수로 전달됩니다.
$ jobs [1]- Stopped cat [2]+ Stopped sed 'p' $ complete -j ./list_job_attrib.sh $ ./list_job_attrib.sh [TAB][TAB] cat sed
백그라운드 작업과 관련해서는 리눅스 백그라운드 작업 관리 방법도 함께 알아두시면 좋습니다.
6. 접두사(Prefix)와 접미사(Suffix)를 활용한 자동 완성
자동 완성 시 실제 완성 값 앞에 추가할 접두사와 뒤에 덧붙일 접미사를 지정할 수도 있습니다. 다음 예시는 list_job_attrib.sh에 대해 접두사와 접미사를 정의한 것입니다.
$ jobs [1]+ Stopped cat $ complete -P '">' -S '<"' ./list_job_attrib.sh $ ./list_job_attrib.sh [TAB][TAB] $ ./list_job_attrib.sh ">cat<"
7. 특정 확장자를 제외한 파일명·디렉터리 자동 완성
어떤 스크립트가 실행을 마치고 그 결과물을 output 디렉터리에 저장한다고 가정해 보겠습니다.
$ cd output/ $ ls all_calls.txt incoming_calls.txt outgoing_calls.txt missed_calls.txt parser_mod.tmp extract.o
위 상황에서 ls 명령어의 자동 완성 시 .tmp와 .o 파일을 제외하고 싶다면 다음과 같이 설정합니다.
$ export FIGNORE='.tmp:.o' $ complete -f -d ls $ cd output $ ls [TAB][TAB] all_calls.txt incoming_calls.txt outgoing_calls.txt missed_calls.txt
FIGNORE는 제외할 파일명 접미사(suffix)를 담고 있는 셸 변수로, 여기에 지정된 확장자는 자동 완성 목록에서 제외됩니다.
8. IFS로 문자열을 분할하여 자동 완성 값 얻기
-W 옵션으로 단어 목록(wordlist)을 지정하면, 해당 문자열이 IFS 변수의 값을 기준으로 분할됩니다. 그런 다음 각 단어가 확장(expansion)되어 자동 완성 목록으로 표시됩니다.
$ export IFS=" " $ complete -W "bubble quick" ./sort_numbers.sh $ ./sort_numbers.sh [TAB][TAB] bubble quick
위에서 볼 수 있듯이 문자열이 IFS 구분자로 분할된 후 각 단어가 확장되므로, 다음과 같이 변수를 활용하는 것도 가능합니다.
$ echo $SORT_TYPE1 bubble $ echo $SORT_TYPE2 quick $ complete -W "$SORT_TYPE1 $SORT_TYPE2" ./sort_numbers.sh $ ./sort_numbers.sh [TAB][TAB] bubble quick
9. 사용자 정의 함수로 자동 완성 생성하기
함수를 포함하여 자동 완성을 정의할 수도 있습니다. -F 옵션으로 함수 이름을 complete 명령에 전달하면, 자동 완성을 생성하기 위해 해당 함수가 실행됩니다. 예를 들어 다음과 같이 함수를 작성할 수 있습니다.
_parser_options()
{
local curr_arg;
curr_arg=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=( $(compgen -W '-i --incoming -o --outgoing -m --missed' -- $curr_arg ) );
}
위 함수에서 각 요소의 역할은 다음과 같습니다.
- COMPREPLY : [TAB][TAB] 키를 눌렀을 때 표시될 자동 완성 결과를 담는 배열입니다.
- COMP_WORDS : 명령줄에 입력된 단어들을 담고 있는 배열입니다.
- COMP_CWORD : COMP_WORDS 배열의 인덱스로, 이를 통해 명령줄의 다른 위치에 있는 단어들에 접근할 수 있습니다.
- compgen :
-W에는 가능한 자동 완성 후보들이 들어가며, $curr_arg 값을 기준으로 해당 인수가 선택됩니다.
parser_option 파일에 있는 이 함수를 다음과 같이 소싱(sourcing)합니다.
$ source parser_option
그리고 이 함수를 파서(parser) 스크립트에 연결합니다.
$ complete -F _parser_options ./parser.pl $ ./parser.pl [TAB][TAB] -i --incoming -o --outgoing -m --missed
위와 같이 파서의 옵션들이 _parser_options() 함수에 의해 자동으로 생성됩니다.
참고: 프로그래밍 가능한 자동 완성에 사용할 수 있는 더 많은 함수들은 /etc/bash_completion 파일에서 확인할 수 있습니다.
10. 1차 스펙이 결과를 생성하지 못할 때의 보조 스펙
정의된 자동 완성 스펙(specification)이 일치하는 결과를 생성하지 못하는 경우, -o 옵션으로 지정된 comp-option이 자동 완성에 사용됩니다.
$ complete -F _count_files -o dirnames ./countfiles.sh
위 예시에서는 ./countfiles.sh 파일에 대해 _count_files 함수로 자동 완성이 정의되어 있습니다. 만약 _count_files() 함수가 일치하는 결과를 생성하지 못하면, 디렉터리 자동 완성이 대신 시도됩니다.
$ ls countfiles.sh dir1/ dir2/ dir3/ $./countfiles.sh [TAB][TAB] dir1 dir2 dir3