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'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!

share|improve this question

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.

share|improve this answer

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: http://stackoverflow.com/questions/43632/can-you-make-just-part-of-a-regex-case-insensitive

Then, regarding the multi-word completion, here is another answer: http://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)

share|improve this answer
"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 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.