Comment rendre les arguments cd insensibles à la casse?

9

Parfois, lors de l'accès aux différents répertoires, il m'arrive la plupart du temps de me souvenir des noms ou au moins d'une partie des noms d'un répertoire sous notre système Linux. Mais certains des répertoires sont nommés en commençant par les premiers majuscules des caractères ou l'un des caractères au milieu du nom Majuscule.

Quelqu'un peut-il suggérer comment rendre les arguments suivants cdinsensibles à la casse de commande, de sorte que si j'exécute cd BackupDirectoryou cd backupdirectoryqu'il puisse entrer le nom de répertoire BackupDirectory.

Bien sûr, je ne veux pas gâcher les choses pour les autres utilisateurs, donc si ce qui précède est possible, est-il possible que le changement puisse être appliqué uniquement à la session que j'utilise et n'affecte pas les autres utilisateurs?

Ok, j'ai essayé set completion-ignore-casemais ça ne marche pas. Cela aide simplement si je tape cd bet / Tabou Esc Escs'il remplit le nom du répertoire en ignorant la casse. Mais, ce dont j'ai besoin, c'est que si je fais un cd backupdirectory, il ignore simplement le cas et entre BackupDirectoryde lui-même.

Ankit Vashistha
la source
Comment allez-vous éviter l'ambiguïté? Si vous avez backUPet backUpcomment ne backuppas dans quel répertoire vous voulez aller?
Bernhard
Quel shell utilisez-vous?
Gert van den Berg
Avez-vous envisagé d'utiliser un outil comme mcou de passer à une interface graphique? Rend la vie beaucoup plus facile.
ott--

Réponses:

17

L'activation cdspellaidera:

shopt -s cdspell

Depuis la manpage:

cdspell S'il est défini, des erreurs mineures dans l'orthographe d'un composant de répertoire dans une commande cd seront corrigées. Les erreurs recherchées sont des caractères transposés, un caractère manquant et un caractère de trop. Si une correction est trouvée, le nom du fichier corrigé est imprimé et la commande s'exécute. Cette option n'est utilisée que par les shells interactifs.

dogbane
la source
Devez-vous faire quoi que ce soit après avoir exécuté cette commande pour que la modification soit effective?
Nathan Arthur
Je suppose que parce que simplement entrer shopt -s cdspell ne fait rien pour moi
sdfsdf
10

Frapper

set completion-ignore-case onen ~/.inputrc(ou bind 'set completion-ignore-case on'en ~/.bashrc) serait ma recommandation. Si vous allez taper le nom complet, pourquoi rechigner à quelques pressions sur la Shifttouche?

Mais si vous le voulez vraiment, voici un wrapper cdqui essaie une correspondance exacte, et s'il n'y en a pas, recherche une correspondance insensible à la casse et l'exécute si elle est unique. Il utilise l' nocasegloboption shell pour la globalisation insensible à la casse et transforme l'argument en glob en ajoutant @()(ce qui ne correspond à rien et nécessite extglob). L' extgloboption doit être activée lors de la définition de la fonction, sinon bash ne peut même pas l'analyser. Cette fonction n'est pas prise en charge 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

Pendant que j'y suis, voici une fonction similaire pour ksh93. La ~(i)modification pour une correspondance insensible à la casse semble être incompatible avec le /suffixe pour correspondre uniquement aux répertoires (cela peut être un bogue dans ma version de ksh). J'utilise donc une stratégie différente pour éliminer les non-répertoires.

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

Enfin, voici une version zsh. Encore une fois, autoriser une complétion insensible à la casse est probablement la meilleure option. Le paramètre suivant revient à un remplacement insensible à la casse s'il n'y a pas de correspondance exacte:

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

Supprimer ''pour afficher toutes les correspondances insensibles à la casse même s'il existe une correspondance exacte à la casse. Vous pouvez définir cela à partir de l'interface de menu 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- arrête d'être méchant'
la source
1
C'est bien. Mais vous devrez l'ajouter inputrcpour que cela fonctionne. Comme ça:echo "set completion-ignore-case on" >> ~/.inputrc
jsejcksn
@JesseJackson Oui, c'était implicite ici parce que le demandeur le savait déjà, mais je vais l'ajouter à ma réponse pour les futurs visiteurs.
Gilles 'SO- arrête d'être méchant'
J'obtiens l'erreur suivante lorsque j'essaie d'utiliser un cd avec ceci: cd:cd:17: no such file or directory: videos(j'ai un Videos
répertoire
@ user7000 Quelle version, sous quel shell?
Gilles 'SO- arrête d'être méchant'
1
@ user7000 Fonctionne pour moi sous zsh 5.0.7. Peut-être avez-vous défini une option qui modifie le fonctionnement du globbing? Est-ce que ça aide si vous changez emulate -L zshpour emulate -LR zsh? (Soit dit en passant, je viens de corriger un bug, qui aurait dû l'être emulate -L zsh, emulate zshsinon, cela gâcherait vos options de shell.)
Gilles 'SO- arrête d'être mauvais'