Suppose I have a bash function specialcat that cats a file in the ~/Special directory

specialcat () {
    cat ~/Special/$1

Suppose the ~/Special directory was set up like so:

mkdir ~/Special
echo This is the first special file > ~/Special/firstfile
echo This is the second special file > ~/Special/secondfile

The specialcat function is used like:

> specialcat firstfile
This is the first special file

I want to enable argument completion so that

> specialcat firstf[TAB]


> specialcat firstfile

regardless of what the current working directory is and what files happen to be there.

This is my attempt so far

_options_specialcat () {
    COMPREPLY=( $(compgen -W "$(ls ~/Special)") )

complete -F _options_specialcat specialcat

which leads to

> specialcat firstf[TAB]
firstfile   secondfile  
> specialcat firstf

That is, pressing tab on a partial file name will display the list of files, but will not complete the command.

How do I alter my _options_specialcat function to produce the desired behavior?

  • COMPREPLY=( $(compgen -W "$(ls ~/Special)" -- "$1") ) Commented Jul 1, 2016 at 4:35
  • Now nothing happens when I TAB. I'm on OSX if that makes a difference.
    – panofsteel
    Commented Jul 1, 2016 at 11:36
  • I changed it to COMPREPLY=( $(compgen -W "$(ls ~/Special)" -- "$2") ) and it worked! If you post as an answer I will gladly accept it.
    – panofsteel
    Commented Jul 1, 2016 at 12:27

1 Answer 1


You need to filter the list by the current argument, so:

COMPREPLY=( $(compgen -W "$(ls ~/Special)" -- "$2") )
  • 1
    For future readers, you can also access the current word with ${COMP_WORDS[COMP_CWORD]} rather than hard-coding the parameter number.
    – panofsteel
    Commented Jul 2, 2016 at 2:28

You must log in to answer this question.

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