Come rendere INsensitive gli argomenti cd?


9

A volte, mentre accedo alle varie directory, accade la maggior parte delle volte che ricordo i nomi o almeno parte dei nomi di una directory nel nostro sistema Linux. Ma alcune delle directory hanno un nome che inizia con i primi caratteri maiuscoli o uno dei caratteri in mezzo al nome Maiuscolo.

Qualcuno può suggerire come posso fare gli argomenti seguendo il cdcomando case INSENSITIVE, in modo che se eseguo cd BackupDirectoryo cd backupdirectorypotrebbe inserire il nome della directory BackupDirectory.

Ovviamente non voglio rovinare le cose per altri utenti, quindi se quanto sopra è possibile, è possibile che la modifica possa essere applicata solo alla sessione che sto usando e non abbia effetto su altri utenti?

Ok, ci ho provato set completion-ignore-casema questo non funziona. Aiuta solo nel senso che se digito cd bed Tabo Esc Escsi riempie il nome della directory ignorando il caso. Ma ciò di cui ho bisogno è che se lo faccio cd backupdirectory, ignora il caso ed entra BackupDirectoryda solo.


Come eviterai l'ambiguità? Se hai backUPe backUpcome, backupno, in quale directory vuoi andare?
Bernhard,

Quale shell stai usando?
Gert van den Berg,

Hai mai pensato di utilizzare uno strumento simile mco passare a una GUI? Semplifica la vita.
ott--

Risposte:


17

L'abilitazione cdspellaiuterà:

shopt -s cdspell

Dalla manpagina:

cdspell Se impostato, gli errori minori nell'ortografia di un componente della directory in un comando cd verranno corretti. Gli errori controllati sono caratteri trasposti, un carattere mancante e un carattere in eccesso. Se viene trovata una correzione, viene stampato il nome del file corretto e il comando procede. Questa opzione è utilizzata solo dalle shell interattive.


Devi fare qualcosa dopo aver eseguito questo comando per rendere effettiva la modifica?
Nathan Arthur

Suppongo di sì perché semplicemente entrare in shopt-s cdspell non sta facendo nulla per me
sdfsdf

10

bash

set completion-ignore-case onin ~/.inputrc(o bind 'set completion-ignore-case on'in ~/.bashrc) sarebbe la mia raccomandazione. Se hai intenzione di digitare il nome completo, perché lasciar perdere a poche pressioni del Shifttasto?

Ma se lo vuoi davvero, ecco un wrapper cdche cerca una corrispondenza esatta e, se non ce n'è, cerca una corrispondenza senza distinzione tra maiuscole e minuscole e la esegue se è unica. Utilizza l' nocaseglobopzione shell per il globbing senza distinzione tra maiuscole e minuscole e trasforma l'argomento in un glob aggiungendo @()(che non corrisponde a nulla e richiede extglob). L' extglobopzione deve essere attivata durante la definizione della funzione, altrimenti bash non può nemmeno analizzarla. Questa funzione non supporta 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

Mentre ci sono, ecco una funzione simile per ksh93. La ~(i)modifica per la corrispondenza senza distinzione tra maiuscole e minuscole sembra essere incompatibile con il /suffisso per abbinare solo le directory (questo potrebbe essere un bug nella mia versione di ksh). Quindi uso una strategia diversa per eliminare le non-directory.

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

Infine, ecco una versione zsh. Ancora una volta, consentire il completamento senza distinzione tra maiuscole e minuscole è probabilmente l'opzione migliore. La seguente impostazione ritorna al globbing senza distinzione tra maiuscole e minuscole se non esiste una corrispondenza esatta del caso:

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

Rimuovi ''per mostrare tutte le corrispondenze senza distinzione tra maiuscole e minuscole anche se esiste una corrispondenza tra maiuscole e minuscole. Puoi impostarlo dall'interfaccia del menu di 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
}

1
Questo è fantastico Ma dovrai aggiungerlo perché inputrcfunzioni. In questo modo:echo "set completion-ignore-case on" >> ~/.inputrc
jsejcksn l'

@JesseJackson Sì, era implicito qui perché il richiedente lo sapeva già, ma lo aggiungerò alla mia risposta per i futuri visitatori.
Gilles 'SO- smetti di essere malvagio'

Ottengo il seguente errore quando provo ad usare cd con questo: cd:cd:17: no such file or directory: videos(Ho una dir chiamata Videos)
Sridhar Sarnobat

@ user7000 Quale versione, sotto quale shell?
Gilles 'SO- smetti di essere malvagio' il

1
@ user7000 Funziona per me con zsh 5.0.7. Forse hai impostato un'opzione che cambia il modo in cui funziona il globbing? Aiuta se cambi emulate -L zsha emulate -LR zsh? (A proposito, ho appena risolto un bug, che avrebbe dovuto essere emulate -L zshno emulate zsh, altrimenti avrebbe confuso le opzioni della tua shell.)
Gilles 'SO- smetti di essere malvagio'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.