@@ -457,6 +457,54 @@ _comp_cmd_sftp()
457457# things we want to backslash escape in scp paths
458458_comp_cmd_scp__path_esc=' [][(){}<>"' " '" ' ,:;^&!$=?`\\|[:space:]]'
459459
460+ # Escape shell special characters in filenames by backslash. This also
461+ # suffixes a space or a slash based on the file type.
462+ #
463+ # Note: With a non-empty prefix ($1 of _comp_xfunc_scp_compgen_local_files),
464+ # Bash will not recognize any filenames, so we need to perform the proper
465+ # quoting manually. We also need to manually suffix a space or a slash based
466+ # on the file type because "-o nospace" is specified. One might think of using
467+ # "compopt +o nospace" instead, but it would suffix a space to directory names
468+ # unexpectedly.
469+ #
470+ # Options:
471+ # -d Only directory names are selected.
472+ # @param $1 escape_replacement - If a non-empty value is specified, special
473+ # characters are replaced with the specified value (instead of the default
474+ # '\\&').
475+ # @stdin List of filenames in the "ls -1F" format, where filenames are
476+ # separated by newlines, and characters /=@|* are suffixed based on the
477+ # types of the files.
478+ _comp_cmd_scp__escape_path ()
479+ {
480+ local OPTIND=1 OPTARG=" " OPTERR=0 opt dirs_only=" "
481+ while getopts ' :d' _flag " $@ " ; do
482+ case $_flag in
483+ d) dirs_only=set ;;
484+ * )
485+ echo " bash_completion: $FUNCNAME : usage error: $* " >&2
486+ return 1
487+ ;;
488+ esac
489+ done
490+ shift " $(( OPTIND - 1 )) "
491+ local escape_replacement=${1:- ' \\&' }
492+
493+ if [[ $dirs_only ]]; then
494+ # escape problematic characters; remove non-dirs
495+ command sed \
496+ -e ' /[^/]$/d' \
497+ -e ' s/' " $_comp_cmd_scp__path_esc " ' /' " $escape_replacement " ' /g'
498+ else
499+ # escape problematic characters; remove executables, aliases, pipes
500+ # and sockets; add space at end of file names
501+ command sed \
502+ -e ' s/[*@|=]$//g' \
503+ -e ' s/' " $_comp_cmd_scp__path_esc " ' /' " $escape_replacement " ' /g' \
504+ -e ' s/[^/]$/& /g'
505+ fi
506+ }
507+
460508# Complete remote files with ssh. Returns paths escaped with three backslashes
461509# (unless -l option is provided).
462510# Options:
@@ -501,20 +549,10 @@ _comp_xfunc_scp_compgen_remote_files()
501549 fi
502550
503551 local _files
504- if [[ $_dirs_only ]]; then
505- # escape problematic characters; remove non-dirs
506- _files=$( ssh -o ' Batchmode yes' " $_userhost " \
507- command ls -aF1dL " $_path *" 2> /dev/null |
508- command sed -e ' s/' " $_comp_cmd_scp__path_esc " ' /' " $_escape_replacement " ' /g' -e ' /[^/]$/d' )
509- else
510- # escape problematic characters; remove executables, aliases, pipes
511- # and sockets; add space at end of file names
512- _files=$( ssh -o ' Batchmode yes' " $_userhost " \
513- command ls -aF1dL " $_path *" 2> /dev/null |
514- command sed -e ' s/[*@|=]$//g' \
515- -e ' s/' " $_comp_cmd_scp__path_esc " ' /' " $_escape_replacement " ' /g' \
516- -e ' s/[^/]$/& /g' )
517- fi
552+ _files=$( ssh -o ' Batchmode yes' " $_userhost " \
553+ command ls -aF1dL " $_path *" 2> /dev/null |
554+ _comp_cmd_scp__escape_path ${_dirs_only: +' -d' } -- \
555+ " $_escape_replacement " )
518556 _comp_compgen -R split -l -- " $_files "
519557}
520558
@@ -539,20 +577,10 @@ _comp_xfunc_scp_compgen_local_files()
539577
540578 local files
541579 _comp_expand_glob files ' "$cur"*' || return 0
542- if [[ $_dirs_only ]]; then
543- _comp_compgen -RU files split -l ${1: +-P " $1 " } -- " $(
544- command ls -aF1dL " ${files[@]} " 2> /dev/null |
545- command sed -e " s/$_comp_cmd_scp__path_esc /\\\\ &/g" \
546- -e ' /[^/]$/d'
547- ) "
548- else
549- _comp_compgen -RU files split -l ${1: +-P " $1 " } -- " $(
550- command ls -aF1dL " ${files[@]} " 2> /dev/null |
551- command sed -e ' s/[*@|=]$//g' \
552- -e " s/$_comp_cmd_scp__path_esc /\\\\ &/g" \
553- -e ' s/[^/]$/& /g'
554- ) "
555- fi
580+ _comp_compgen -RU files split -l ${1: +-P " $1 " } -- " $(
581+ command ls -aF1dL " ${files[@]} " 2> /dev/null |
582+ _comp_cmd_scp__escape_path ${_dirs_only: +' -d' }
583+ ) "
556584}
557585
558586# @deprecated 2.12
0 commit comments