I've got a simple command named th. I've got a bash-completion file for it that goes as follows:

_th()  {
  local curr=${COMP_WORDS[COMP_CWORD]}
  COMPREPLY=( $(compgen -f -X '!*.@(tar|tar.xz|tar.bz2|tar.gz|tbz|tgz)' -- "$curr") )
complete -F _th -o filenames th

This works as intended, for the most part. For arguments to my th function, BASH only tab-completes files ending in .tar, .tar.xz, etc. Two problems:

  1. The matching is case-sensitive. Not all tar files have lower-case extensions. (Using shopt to set nocaseglob inside the bash-completion file doesn't work.)

  2. The matching chokes on multi-word filenames, e.g. files with spaces in their names.

    [rsaw:blahb]$ ls
    bam.tgz  boom.TGZ  sad.TAR  spaces in this-file.tbz
    [rsaw:blahb]$ th<tabtab>
    bam.tgz        in             spaces         this-file.tbz  
    [rsaw:blahb]$ th spa<tabtab>
    in             spaces         this-file.tbz  
    [rsaw:blahb]$ th spaces<tabtab>   # At this point I added a backslash and pressed tab until 4 backslashes appeared
    in             spaces         this-file.tbz  
    [rsaw:blahb]$ th spaces\\\\<tabtab>   # At this point, nothing else happened 

Any help appreciated!


Not sure if this is still an issue for you but I ran into something similar while trying to get mid-word filename completion and have some ideas for possible solutions.

Changing the IFS variable by adding local IFS=$'\n' fixed the problem with spaces in filenames for me, might be worth a try.

As for making things case-insensitive, you could force $curr to lowercase for compgen by using ${cur,,}. Full function would look like this after both changes:

_th()  {
  local IFS=$'\n'
  local curr=${COMP_WORDS[COMP_CWORD]}
  COMPREPLY=( $(compgen -f -X '!*.@(tar|tar.xz|tar.bz2|tar.gz|tbz|tgz)' -- "${curr,,}") )
complete -F _th -o filenames th

That would make the whole filename matching case-insensitive. If you only want the extension case insensitive you could do some string manipulation to $cur to make only the extension lowercase.


You could do two things with your regex regarding the file-type extension. You could add the all-caps extensions directly to the regex, i.e. (tar|TAR) or you can add the ?i flag to make the search case-insensitive. See this for a guide: https://stackoverflow.com/questions/43632/can-you-make-just-part-of-a-regex-case-insensitive

Then, regarding the multi-word completion, here is another answer: https://stackoverflow.com/questions/1146098/properly-handling-spaces-and-quotes-in-bash-completion (I personally use _ instead of spaces in all my files for this reason)

  • "you can add the ?i flag to make the search case-insensitive." --> Thanks for pointing me to that. I use a lot of regular expressions in other work I do and I'd never seen that before; however, it doesn't work for bash file globbing. Thanks for the link to the other answer... We'll see if I can get some inspiration from that. – rsaw Jan 20 '13 at 17:18

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.