@@ -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 executable, symlink, pipe,
500+         #  socket and door indicators; 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