To request that a command be completed like another command that is already known to the completion system, you can use the compdef my_command=known_command
form of compdef
.
compdef s=ssh
compdef {cxterm,uxterm,xterm-color}=xterm
Under the hood, this is basically equivalent to _comps[s]=$_comps[ssh]
.
Some completion commands apply to a family of functions and read the first word of the command line to determine which particular command to complete. For example, the commands ssh
, scp
, sftp
and a few more are all completed by the function _ssh
. In that case, you need to tell the completion function which “service” your function is like (by default, the service is the executable name, here your function's name).
_s () {
local service=ssh
_ssh "$@"
}
compdef _s s
Believe it might be better to use compgen
instead of find
in this case.
You probably already have a completion script with system. Try e.g.
locate bash_completion
On Debian variants this is probably:
/usr/share/bash-completion/bash_completion
where you find e.g. _filedir
. So the simplest way then would be something in the direction of:
*)
pushd "/some/path" >/dev/null
_filedir
popd >/dev/null
If that is not an option this could be a starter:
_comp_by_path()
{
local opt cur dir
local IFS=$'\n' x tmp
local -a tokens
opt="$1"
cur="$2"
dir="$3"
# Enter target directory
pushd "$dir" >/dev/null
# Get directories, filtered against current
[[ "$opt" != "-f" ]] && \
x=$( compgen -d -- "$cur" ) &&
while read -r tmp; do
tokens+=( "$tmp" )
done <<< "$x"
# Get files, filtered against current
[[ "$opt" != "-d" ]] && \
x=$( compgen -f -- "$cur" ) &&
while read -r tmp; do
tokens+=( "$tmp" )
done <<< "$x"
# If anything found
if [[ ${#tokens[@]} -ne 0 ]]; then
# Make sure escaping is OK
compopt -o filenames 2>/dev/null
COMPREPLY+=( "${tokens[@]}" )
fi
# Go back
popd >/dev/null
}
_GetOptMyCommand()
{
local cur
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "-h -l --help --list --" -- "$cur" ) );;
*)
_comp_by_path "any" "$cur" "/some/path"
esac
}
complete -F _GetOptMyCommand my_command
A variant using find
could be something in direction of this:
_zaso()
{
local dir="$1"
pushd "$dir" >/dev/null
find * -maxdepth 0 2>/dev/null
popd >/dev/null
}
_comp_with_find()
{
local cur dir
local IFS=$'\n'
cur="$1"
dir="$2"
compopt -o filenames 2>/dev/null
COMPREPLY=( $( compgen -W "$(_zaso "$dir")" -- "$cur" ) );
}
Also note that printf
in Bash has a %q
option. So to generate quoted strings this is an option to play with:
find * -maxdepth 0 2>/dev/null && \
while read -r tmp; do
printf "%q\n" "$tmp"
done <<< "$x"
Also not that file names can have newline characters in which a lot of this will break. Have not found a way to use \0
with compgen
.
Best Answer
You can see the current configuration with
and the definition of the used shell function with
There is a
complete
feature / option-X
which allows to filter the results. The problem is that this applies only to tocomplete
actions. It does not apply to the-o default
results (I don't know about-o bashdefault
).You can change the compspec:
Unfortulately
you can have only one
-X
in thecomplete
call (former ones are overwritten)you need
shopt -s extglob
for the above to work; otherwise you are limited to a single name or pattern ("*.log"
)