Let's say I have a filename and different extensions to it:


It is easier to type just the filename without extension, then the whole filename. This is possible, because corresponding program know the extension which they need and append it automatically. The following examples work perfectly:

tex test
pdf-viewer test

But using bash completion here constantly annoys me by adding the trailing dot. For example:

tex te<TAB>

is turned into

tex test.

But the application will fail with error; I have to hit backspace each time after I hit <TAB> :-(

How to tell bash not to add trailing dot when doing autocompletion?

  • Bash autocompletes the longest common prefix. That in your case the longest common prefix ends in a dot is an accident. – AlexP Feb 10 '17 at 7:22
  • 1
    @AlexP this does not prove that it is not possible to tell bash to exclude this dot from autocompletion – Igor Liferenko Feb 13 '17 at 1:33
  • Note that accepting test in place of test.tex is a convenience, not a requirement. One option is modify the completion for tex to only expand to names ending in .tex. I know it involves the -G option to the complete command, but I can never figure out how to make it work correctly. I'll post an answer if I do. – chepner Sep 28 '17 at 20:34

There might be an easier way, but this seems to work:

texfiles () { names=( "$2"*.tex ); COMPREPLY=( "${names[@]%.tex}" ); }

complete -F texfiles tex

This first sets up a shell function called texfiles. It uses the second command line argument ($2, the word typed by the user on the command line before pressing Tab to complete the word), and populates the COMPREPLY array with all names that matches "$2"*.tex.

For each of these names, the suffix .tex is removed before adding it to the array.

The complete command is then used to tell the shell to execute the texfiles function for file name completion for the tex command specifically. You may repeat the same complete command for all commands that should complete .tex files in the same way. For pdf-viewer you may want to create a corresponding pdffiles function (the names of these functions are arbitrary).

This is it in action (<tab> signifies me pressing the Tab key):

bash-4.4$ ls -l
total 0
-rw-r--r--  1 kk  wheel  0 Sep 28 21:43 README.txt
-rw-r--r--  1 kk  wheel  0 Sep 28 21:12 file.tex
-rw-r--r--  1 kk  wheel  0 Sep 28 21:24 file2.tex
-rw-r--r--  1 kk  wheel  0 Sep 28 21:25 hello.tex

bash-4.4$ tex <tab><tab>
file   file2  hello
bash-4.4$ tex

bash-4.4$ tex f<tab>ile<tab><tab>
file   file2
bash-4.4$ tex file

(the ile in file is inserted by the shell)

Read the "Programmable Completion" section of the bash manual for the gory details.

  • 1
    You could replace the for loop with an array operation: arr=("$2"*.tex); COMPREPLY=( "${arr[@]%.tex}"). – chepner Sep 28 '17 at 20:18

Add a custom completion spec for the tex command to your .bashrc. After specifying that tex should use filename completion, you can add a filter to remove any argument that doesn't match *.tex from the possible completions.

complete -f -X '!*.tex'

Now, if you had test.tex, test.aux, and test.pdf in your directory, a prefix of test would only complete to test.tex. This completes the full name of the file you want, rather than skipping the . to create the shortcut.

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.