6

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?

8
+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.

  • Cool... What about making it only be for the current session? – Questionmark Jun 10 '14 at 14:35
  • 2
    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 '14 at 16:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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