4

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

_th()  {
  COMPREPLY=()
  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!

2 Answers 2

1

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.

-1

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)

1
  • "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
    Commented Jan 20, 2013 at 17:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .