¿Cómo hacer que los argumentos de CD sean insensibles?

9

A veces, mientras accedo a los distintos directorios, sucede la mayoría de las veces que recuerdo los nombres o al menos parte de los nombres de un directorio en nuestro sistema Linux. Pero algunos de los directorios se nombran comenzando con las mayúsculas del primer carácter o uno de los caracteres en el medio del nombre Mayúscula.

¿Alguien puede sugerir cómo puedo hacer que los argumentos que siguen al cdcaso del comando sean INSENSIBLES, de modo que si lo ejecuto cd BackupDirectoryo cd backupdirectorypodría ingresar el nombre del directorio BackupDirectory?

Por supuesto, no quiero arruinar las cosas para otros usuarios, así que si lo anterior es posible, ¿es posible que el cambio se pueda aplicar solo a la sesión que estoy usando y no afecte a otros usuarios?

Ok, lo probé set completion-ignore-casepero esto simplemente no funciona. Sólo ayuda en que si escribo cd by Tab, o Esc Escse llena el nombre del directorio ignorando el caso. Pero, lo que necesito es que si hago un cd backupdirectory, simplemente ignora el caso y entra BackupDirectorypor sí solo.

Ankit Vashistha
fuente
¿Cómo evitarás la ambigüedad? Si tiene backUPy backUp, ¿cómo backupno a qué directorio desea ir?
Bernhard
¿Qué caparazón estás usando?
Gert van den Berg
¿Has considerado usar una herramienta como mco cambiar a una GUI? Hace la vida mucho más fácil.
ott--

Respuestas:

17

La habilitación cdspellayudará a:

shopt -s cdspell

De la manpágina:

cdspell Si se establece, se corregirán los errores menores en la ortografía de un componente de directorio en un comando de cd. Los errores verificados son caracteres transpuestos, un carácter que falta y un carácter demasiado. Si se encuentra una corrección, se imprime el nombre del archivo corregido y el comando continúa. Esta opción solo la usan los shells interactivos.

dogbane
fuente
¿Tiene que hacer algo después de ejecutar este comando para que el cambio surta efecto?
Nathan Arthur
Supongo que sí porque simplemente ingresar shopt -s cdspell no está haciendo nada por mí
sdfsdf
10

Golpetazo

set completion-ignore-case onen ~/.inputrc(o bind 'set completion-ignore-case on'en ~/.bashrc) sería mi recomendación. Si va a escribir el nombre completo, ¿por qué rechazar unas pocas pulsaciones de la Shifttecla?

Pero si realmente lo quiere, aquí hay una envoltura cdque intenta una coincidencia exacta, y si no hay ninguna, busca una coincidencia entre mayúsculas y minúsculas y la realiza si es única. Utiliza la nocaseglobopción de shell para el globbing que no distingue entre mayúsculas y minúsculas, y convierte el argumento en un glob al agregarlo @()(que no coincide con nada y requiere extglob). La extglobopción tiene que estar activada cuando se define la función, de lo contrario bash ni siquiera puede analizarla. Esta función no es compatible CDPATH.

shopt -s extglob
cd () {
  builtin cd "$@" 2>/dev/null && return
  local options_to_unset=; local -a matches
  [[ :$BASHOPTS: = *:extglob:* ]] || options_to_unset="$options_to_unset extglob"
  [[ :$BASHOPTS: = *:nocaseglob:* ]] || options_to_unset="$options_to_unset nocaseglob"
  [[ :$BASHOPTS: = *:nullglob:* ]] || options_to_unset="$options_to_unset nullglob"
  shopt -s extglob nocaseglob nullglob
  matches=("${!#}"@()/)
  shopt -u $options_to_unset
  case ${#matches[@]} in
    0) # There is no match, even case-insensitively. Let cd display the error message.
      builtin cd "$@";;
    1)
      matches=("$@" "${matches[0]}")
      unset "matches[$(($#-1))]"
      builtin cd "${matches[@]}";;
    *)
      echo "Ambiguous case-insensitive directory match:" >&2
      printf "%s\n" "${matches[@]}" >&2
      return 3;;
  esac
}

Ksh

Mientras estoy en eso, aquí hay una función similar para ksh93. La ~(i)modificación para la coincidencia que no distingue entre mayúsculas y minúsculas parece ser incompatible con el /sufijo para hacer coincidir solo los directorios (esto puede ser un error en mi versión de ksh). Entonces uso una estrategia diferente, para eliminar los no directorios.

cd () {
  command cd "$@" 2>/dev/null && return
  typeset -a args; typeset previous target; typeset -i count=0
  args=("$@")
  for target in ~(Ni)"${args[$(($#-1))]}"; do
    [[ -d $target ]] || continue
    if ((count==1)); then printf "Ambiguous case-insensitive directory match:\n%s\n" "$previous" >&2; fi
    if ((count)); then echo "$target"; fi
    ((++count))
    previous=$target
  done
  ((count <= 1)) || return 3
  args[$(($#-1))]=$target
  command cd "${args[@]}"
}

Zsh

Finalmente, aquí hay una versión zsh. Nuevamente, permitir la finalización sin distinción entre mayúsculas y minúsculas es probablemente la mejor opción. La siguiente configuración vuelve a ser insensible a mayúsculas y minúsculas si no hay coincidencia exacta de mayúsculas y minúsculas:

zstyle ':completion:*' '' matcher-list 'm:{a-z}={A-Z}'

Eliminar ''para mostrar todas las coincidencias entre mayúsculas y minúsculas, incluso si hay una coincidencia exacta entre mayúsculas y minúsculas. Puede configurar esto desde la interfaz del menú de compinstall.

cd () {
  builtin cd "$@" 2>/dev/null && return
  emulate -L zsh
  setopt local_options extended_glob
  local matches
  matches=( (#i)${(P)#}(N/) )
  case $#matches in
    0) # There is no match, even case-insensitively. Try cdpath.
      if ((#cdpath)) &&
         [[ ${(P)#} != (|.|..)/* ]] &&
         matches=( $^cdpath/(#i)${(P)#}(N/) ) &&
         ((#matches==1))
      then
        builtin cd $@[1,-2] $matches[1]
        return
      fi
      # Still nothing. Let cd display the error message.
      builtin cd "$@";;
    1)
      builtin cd $@[1,-2] $matches[1];;
    *)
      print -lr -- "Ambiguous case-insensitive directory match:" $matches >&2
      return 3;;
  esac
}
Gilles 'SO- deja de ser malvado'
fuente
1
Esto es genial. Pero deberá agregarlo inputrcpara que funcione. Así:echo "set completion-ignore-case on" >> ~/.inputrc
jsejcksn
@JesseJackson Sí, eso estaba implícito aquí porque el autor de la pregunta ya lo sabía, pero lo agregaré a mi respuesta para futuros visitantes.
Gilles 'SO- deja de ser malvado'
Recibo el siguiente error cuando intento usar cd con esto: cd:cd:17: no such file or directory: videos(Tengo un directorio llamado Videos)
Sridhar Sarnobat
@ user7000 ¿Qué versión, bajo qué shell?
Gilles 'SO- deja de ser malvado'
1
@ user7000 Funciona para mí en zsh 5.0.7. ¿Tal vez has configurado una opción que cambia la forma en que funciona el globbing? ¿Ayuda si cambias emulate -L zsha emulate -LR zsh? (Por cierto que acaba de arreglar un error, que debería haber sido emulate -L zsh, no emulate zsh, de lo contrario sería estropear sus opciones de shell.)
Gilles 'SO- estar parada mal'