local cur _skipdot _cdpath local i j k
# Tilde expansion, with side effect of expanding tilde to full pathname case "$2" in
\~*) eval cur="$2" ;;
*) cur=$2 ;; esac
# no cdpath or absolute pathname -- straight directory completion if [[ -z "${CDPATH:-}" ]] || [[ "$cur" == @(./*|../*|/*) ]]; then
# compgen prints paths one per line; could also use while loop
IFS=$’\n’
COMPREPLY=( $(compgen -d -- "$cur") )
IFS=$’ \t\n’
# CDPATH+directories in the current directory if not in CDPATH else
IFS=$’\n’
_skipdot=false
# preprocess CDPATH to convert null directory names to .
_cdpath=${CDPATH/#:/.:}
_cdpath=${_cdpath//::/:.:}
_cdpath=${_cdpath/%:/:.} for i in ${_cdpath//:/$’\n’}; do if [[ $i -ef . ]]; then _skipdot=true; fi k="${#COMPREPLY[@]}" for j in $( compgen -d -- "$i/$cur" ); do
COMPREPLY[k++]=${j#$i/}
# cut off directory done done
$_skipdot || COMPREPLY+=( $(compgen -d -- "$cur") )
IFS=$’ \t\n’ fi
# variable names if appropriate shell option set and no completions if shopt -q cdable_vars && [[ ${#COMPREPLY[@]} -eq 0 ]]; then
COMPREPLY=( $(compgen -v -- "$cur") ) fi return 0
}
We install the completion function using the -F option to complete:
# Tell readline to quote appropriate and append slashes to directories;
# use the bash default completion for other arguments complete -o filenames -o nospace -o bashdefault -F _comp_cd cd