Como fazer com que argumentos de cd case INsensitive?

9

Às vezes, ao acessar os vários diretórios, acontece na maioria das vezes que eu me lembro dos nomes ou pelo menos parte dos nomes de um diretório em nosso sistema Linux. Mas alguns dos diretórios são nomeados começando com maiúsculas de primeiro caractere ou um dos caracteres no meio do nome Maiúsculas.

Alguém pode sugerir como posso fazer os argumentos seguindo o caso de comando cd INSENSITIVE, de tal forma que se eu executar cd BackupDirectory ou cd backupdirectory ele poderia inserir o nome do diretório BackupDirectory.

É claro que não quero estragar as coisas para os outros usuários, então, se o acima for possível, é possível que a mudança possa ser aplicada apenas na sessão que estou usando e não afeta outros usuários?

Ok, tentei set completion-ignore-case , mas isso simplesmente não funciona. Isso apenas ajuda se eu digitar cd b e Tab ou Esc Esc preenche o nome do diretório ignorando o caso. Mas, o que eu preciso é que se eu fizer um cd backupdirectory , ele simplesmente ignora o caso e insere BackupDirectory sozinho.

    
por Ankit Vashistha 03.01.2013 / 10:55

2 respostas

15

Ativar cdspell ajudará:

shopt -s cdspell

Da página man :

cdspell If set, minor errors in the spelling of a directory component in a cd command will be corrected. The errors checked for are transposed characters, a miss- ing character, and one character too many. If a correction is found, the corrected file name is printed, and the command proceeds. This option is only used by interactive shells.

    
por 03.01.2013 / 12:25
10

Bash

set completion-ignore-case on em ~/.inputrc (ou bind 'set completion-ignore-case on' in ~/.bashrc ) seria minha recomendação. Se você for digitar o nome completo, por que hesitar em alguns pressionamentos da tecla Shift ?

Mas se você realmente quiser, aqui está um wrapper em torno de cd que tenta uma correspondência exata e, se não houver nenhuma, procura uma correspondência sem distinção entre maiúsculas e minúsculas e a executa se for única. Ele usa a opção nocaseglob shell para globbing sem distinção entre maiúsculas e minúsculas e transforma o argumento em glob, anexando @() (que não corresponde a nada e requer extglob ). A opção extglob deve ser ativada ao definir a função, caso contrário, o bash não pode nem analisá-la. Esta função não suporta 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

Enquanto estou nisso, aqui está uma função semelhante para o ksh93. O ~(i) modificado para correspondência que não diferencia maiúsculas de minúsculas parece ser incompatível com o sufixo / para corresponder somente aos diretórios (isso pode ser um bug na minha versão do ksh). Então eu uso uma estratégia diferente, para eliminar diretórios não.

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, aqui está uma versão do zsh. Mais uma vez, permitir a conclusão sem distinção entre maiúsculas e minúsculas é provavelmente a melhor opção. A configuração a seguir recai sobre a globalização sem diferenciação de maiúsculas e minúsculas se não houver correspondência exata entre maiúsculas e minúsculas:

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

Remova '' para exibir todas as correspondências que não diferenciam maiúsculas de minúsculas, mesmo se houver uma correspondência exata. Você pode definir isso na 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
}
    
por 04.01.2013 / 11:04