Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm trying to setup autocompletion for a command, which takes only one parameter, a folder name,

In /secure/kernel_builds/, I have the three following subfolder:

3.5.6/ 3.6.2/ source/

Now I want auto completion, that lists all sub folder name possible, but not the one named source, right now I'm using a pretty stupid way to do it, by checking if the completion word is started with a number,

    case $COMP_CWORD in
            if [[ "${COMP_WORDS[COMP_CWORD]}" =~ ^[0-9] ]];then
                COMPREPLY=( /secure/kernel_builds/"${COMP_WORDS[COMP_CWORD]}"* )
                COMPREPLY=( /secure/kernel_builds/"${COMP_WORDS[COMP_CWORD]}"[0-9]*/ )
            COMPREPLY=( "${COMPREPLY[@]#/secure/kernel_builds/}" )
            COMPREPLY=( "${COMPREPLY[@]%/}" )

Is there a better way of doing so?

share|improve this question

The compgen builtin has a -X argument for this very purpose:

-X filterpat
    filterpat is a pattern as used for filename expansion. It is applied to the list of 
    possible completions generated by the preceding options and arguments, and each 
    completion matching filterpat is removed from the list. A leading ! in filterpat 
    negates the pattern; in this case, any completion not matching filterpat is removed.

So you could probably just do something like:

_avail_kernel_builds() {
    case $COMP_CWORD in
        1) COMPREPLY=( $(cd /secure/kernel_builds; compgen -d -X "source") ) ;;

So compgen -d says "list the folders in the current directory", and -X "source" says "...but filter out anything named "source".

share|improve this answer

You can check in a loop for the strings you (don't) want:

declare -a accept
declare -a reject
for s in "${COMPREPLY[@]}"; do
    if [[ "$s" =~ want ]]; then
        accept=( "${accept[@]}" "$s" )
        reject=( "${reject[@]}" "$s" )
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.