Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

If I start typing a command or filename, I can use the tab key to auto-complete my string.

That is well known...

Is there a way to change the behavior of the auto complete for the current bash session so that it will do certain things?

For example

On pressing Tab Tab in the current session, only files that contain *.txt will be displayed.

Are there certain environment variables or something that could make this work?

share|improve this question
2  
This might be a good starting point for you. gnu.org/software/bash/manual/bash.html#Programmable-Completion –  Ramesh Jun 6 at 17:38
    
I think you can do this for a particular command in bash (complete -X PATTERN) but not for all commands in one go. –  Gilles Jun 6 at 23:22

1 Answer 1

up vote 6 down vote accepted
+50

In the bash_completion mechanism it's the bash function _filedir_xspec() that is responsible for filename and dirname completions. This funtion can be found in the script /etc/bash_completion.

You can edit that function and add a line that contains your regex. For example use this function (it's a copy of the original function):

_filedir_xspec()
{
    local IFS cur xspec

    IFS=$'\n'
    COMPREPLY=()
    _get_comp_words_by_ref cur

    _expand || return 0

    # get first exclusion compspec that matches this command
    xspec=$( awk "/^complete[ \t]+.*[ \t]${1##*/}([ \t]|\$)/ { print \$0; exit }" \
        "$BASH_COMPLETION" )
    # prune to leave nothing but the -X spec
    xspec=${xspec#*-X }
    xspec=${xspec%% *}

    local -a toks
    local tmp

    toks=( ${toks[@]-} $(
        compgen -d -- "$(quote_readline "$cur")" | {
        while read -r tmp; do
            # see long TODO comment in _filedir() --David
            printf '%s\n' $tmp
        done
        }
        ))

    # Munge xspec to contain uppercase version too
    eval xspec="${xspec}"
    eval xspec="!*.txt" #<---- HERE add your regex, that's the only line changed
    local matchop=!
    if [[ $xspec == !* ]]; then
        xspec=${xspec#!}
        matchop=@
    fi
    [[ ${BASH_VERSINFO[0]} -ge 4 ]] && \
        xspec="$matchop($xspec|${xspec^^})" || \
        xspec="$matchop($xspec|$(printf %s $xspec | tr '[:lower:]' '[:upper:]'))"

    toks=( ${toks[@]-} $(
        eval compgen -f -X "!$xspec" -- "\$(quote_readline "\$cur")" | {
        while read -r tmp; do
            [ -n $tmp ] && printf '%s\n' $tmp
        done
        }
        ))
    [ ${#toks[@]} -ne 0 ] && _compopt_o_filenames
    COMPREPLY=( "${toks[@]}" )
}

Notice the new part at line 32:

eval xspec="!*.txt" 

This statement is later used in compgen to remove all entries, that do not match the regular expression. I wouldn't recommend to edit the file /etc/bash_completion. Instead make a new file with the content above and source the file if needed:

source /path/to/file

Now, all commands/applications in the shell, that where completed by the function _filedir_xspec(), complete now only with *.txt filenames.

share|improve this answer
    
Cool... What about making it only be for the current session? –  Questionmark Jun 10 at 14:35
1  
it IS only for the current session. You can copy the function into your shell and it will be away in the next session. But I recommend to source a file that contains the function when you need it. In the next session it's not anymore available. To make it permanent, I would write it one of the rc scripts: ~/.bashrc for example. –  chaos Jun 10 at 16:49

Your Answer

 
discard

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.