I am writing a bash completion script for a command-line tool:
_plink()
{
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="--1 --23file --a1-allele --a2-allele --adjust --aec"
if [[ ${cur} == --*file ]] || [[ ${cur} == --out ]]; then
COMPREPLY=( $(compgen -W "$(ls)" -- ${cur}) )
elif [[ ${cur} == -* ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
}
complete -F _plink plink1.9
The idea is if the after the option --*file
and --out
, bash should autocomplete the file path.
Right now I am using "$(ls)
" which only completes the filenames in current working path. Any suggestions?
You can use compgen -f
to complete filenames, like this:
if [[ ${prev} == --*file ]] || [[ ${prev} == --out ]]; then
COMPREPLY=( $(compgen -f -- ${cur}) )
elif ...
However, compgen -f
isn't great at completing filenames because it doesn't honour spaces in filenames.
A better way is to use the _filedir
function available in bash-completion-lib. It might already be available on your system (type: declare -f _filedir
to check).
Using _filedir
, your completion function becomes:
if [[ ${prev} == --*file ]] || [[ ${prev} == --out ]]; then
_filedir
elif ...
Alternatively if you do not have the bash-completion-lib, I looked at the source of the _filedir() function and was able to get full bash completion using comptopt -o
along with compgen -f
:
if [[ ${prev} == --*file ]] || [[ ${prev} == --out ]]; then
comptopt -o filenames 2>/dev/null
COMPREPLY=( $(compgen -f -- ${cur}) )
elif ...
However, you do not get the functionality of resolving ~usernames or case-insensitivity that _filedir() provides.