Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Sometimes while accessing the various directories it happens most of the times that I remember the names or at least part of the names of a directory under our Linux system. But some of the directories are named starting with first character caps or one of the characters in the middle of the name Upper case.

Can anyone suggest how can I make the arguments following cd command case INSENSITIVE, such that if I perform cd BackupDirectory or cd backupdirectory it could enter the directory name BackupDirectory.

Of course I don't want to screw the things for other users so if the above is possible, is that possible that the change could be applied just to the session I am using and do not effect other users?

Ok, I tried set completion-ignore-case on but this just doesn't work. It just helps in that if I type cd b and Tab or Esc Esc it fills the directory name ignoring the case. But, what I need is if I do a cd backupdirectory, it just ignores the case and enters BackupDirectory on its own.

share|improve this question
    
How will you avoid ambiguity? If you have backUP and backUp, how would backup no to which directory you want to go? –  Bernhard Jan 3 '13 at 10:41
    
Which shell are you using? –  Gert van den Berg Jan 3 '13 at 12:39
    
Have you considered using a tool like mc or switching to a GUI? Makes life much easier. –  ott-- Jan 4 '13 at 20:30
add comment

2 Answers

Enabling cdspell will help:

shopt -s cdspell

From the man page:

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.

share|improve this answer
add comment

Bash

set completion-ignore-case on would be my recommendation. If you're going to type the full name, why balk at a few presses of the Shift key?

But if you really want it, here's a wrapper around cd that tries for an exact match, and if there is none, looks for a case-insensitive match and performs it if it is unique. It uses the nocaseglob shell option for case-insensitive globbing, and turns the argument into a glob by appending @() (which matches nothing, and requires extglob). The extglob option has to be turned on when defining the function, otherwise bash can't even parse it. This function doesn't support 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

While I'm at it, here's a similar function for ksh93. The ~(i) modified for case-insensitive matching seems to be incompatible with the / suffix to match directories only (this may be a bug in my release of ksh). So I use a different strategy, to weed out non-directories.

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

Finally, here's a zsh version. Again, allowing case-insensitive completion is probably the best option. The following setting falls back to case-insensitive globbing if there is no exact-case match:

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

Remove '' to show all case-insensitive matches even if there is an exact-case match. You can set this from the menu interface of compinstall.

cd () {
  builtin cd "$@" 2>/dev/null && return
  emulate 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
}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.