cdpathによる補完
http://d.hatena.ne.jp/parasporospa/20060822/1156226529 よりコピー。
# Turn on extended globbing and programmable completion shopt -s extglob progcomp # This function checks whether a given readline variable # is `on'. # _rl_enabled() { [[ "$( bind -v )" = *$1+([[:space:]])on* ]] } # This function performs file and directory completion. It's better than # simply using 'compgen -f', because it honours spaces in filenames. # If passed -d, it completes only on directories. If passed anything else, # it's assumed to be a file glob to complete on. # _filedir() { local IFS=$'\t\n' xspec #glob _expand || return 0 #glob=$(set +o|grep noglob) # save glob setting. #set -f # disable pathname expansion (globbing) if [ "${1:-}" = -d ]; then COMPREPLY=( ${COMPREPLY[@]:-} $( compgen -d -- $cur ) ) #eval "$glob" # restore glob setting. return 0 fi xspec=${1:+"!*.$1"} # set only if glob passed in as $1 COMPREPLY=( ${COMPREPLY[@]:-} $( compgen -f -X "$xspec" -- "$cur" ) \ $( compgen -d -- "$cur" ) ) #eval "$glob" # restore glob setting. } # This function expands tildes in pathnames # _expand() { [ "$cur" != "${cur%\\}" ] && cur="$cur\\" # expand ~username type directory specifications if [[ "$cur" == \~*/* ]]; then eval cur=$cur elif [[ "$cur" == \~* ]]; then cur=${cur#\~} COMPREPLY=( $( compgen -P '~' -u $cur ) ) return ${#COMPREPLY[@]} fi } # This meta-cd function observes the CDPATH variable, so that cd additionally # completes on directories under those specified in CDPATH. # _cd() { local IFS=$'\t\n' cur=${COMP_WORDS[COMP_CWORD]} i j k # try to allow variable completion if [[ "$cur" == ?(\\)\$* ]]; then COMPREPLY=( $( compgen -v -P '$' -- "${cur#?(\\)$}" ) ) return 0 fi # Use standard dir completion if no CDPATH or parameter starts with /, # ./ or ../ if [ -z "${CDPATH:-}" ] || [[ "$cur" == ?(.)?(.)/* ]]; then _filedir -d return 0 fi local -r mark_dirs=$(_rl_enabled mark-directories && echo y) local -r mark_symdirs=$(_rl_enabled mark-symlinked-directories && echo y) # we have a CDPATH, so loop on its contents for i in ${CDPATH//:/$'\t'}; do # create an array of matched subdirs k=${#COMPREPLY[@]} for j in $( compgen -d $i/$cur ); do if [[ ( $mark_symdirs && -h $j || $mark_dirs && ! -h $j ) && ! -d ${j#$i/} ]]; then j="${j}/" fi COMPREPLY[k++]=${j#$i/} done done _filedir -d if [[ ${#COMPREPLY[@]} -eq 1 ]]; then i=${COMPREPLY[0]} if [ "$i" == "$cur" ] && [[ $i != "*/" ]]; then COMPREPLY[0]="${i}/" fi fi return 0 } nospace="-o nospace" if shopt -q cdable_vars; then complete -v -F _cd $nospace $filenames cd else complete -F _cd $nospace $filenames cd fi