How to make cd arguments case INsensitive?
Solution 1
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.
Solution 2
Bash
set completion-ignore-case on
in ~/.inputrc
(or bind 'set completion-ignore-case on'
in ~/.bashrc
) 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 -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
}
Related videos on Youtube
Ankit Vashistha
Updated on September 18, 2022Comments
-
Ankit Vashistha over 1 year
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 performcd BackupDirectory
orcd 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 typecd b
and Tab or Esc Esc it fills the directory name ignoring the case. But, what I need is if I do acd backupdirectory
, it just ignores the case and entersBackupDirectory
on its own. -
jsejcksn over 8 yearsThis is great. But you will need to add it to
inputrc
for it to work. Like this:echo "set completion-ignore-case on" >> ~/.inputrc
-
Gilles 'SO- stop being evil' over 8 years@JesseJackson Yes, that was implicit here because the asker already knew, but I'll add it to my answer for future visitors.
-
Nathan Arthur over 8 yearsDo you have to do anything after running this command for the change to go into effect?
-
Sridhar Sarnobat over 7 yearsI get the following error when trying to use cd with this:
cd:cd:17: no such file or directory: videos
(I have a dir calledVideos
) -
Gilles 'SO- stop being evil' over 7 years@user7000 Which version, under which shell?
-
Gilles 'SO- stop being evil' over 7 years@user7000 Works for me under zsh 5.0.7. Maybe you've set an option that changes the way globbing works? Does it help if you change
emulate -L zsh
toemulate -LR zsh
? (By the way I just fixed a bug, that should have beenemulate -L zsh
, notemulate zsh
, otherwise it would mess up your shell options.) -
Sridhar Sarnobat over 7 yearsThanks for the reply. For some reason now it is working even without me using any of your code. I guess that's good news though ideally I would understand what changed between now and then (maybe it was permissions related which I was continuing to mess with). I'll follow up if I get further issues.
-
sdfsdf about 7 yearsI would assume so because simply entering shopt -s cdspell is not doing anything for me
-
math2001 almost 7 years+1 for
bind 'set completion-ignore-case on'
in~/.bashrc
-
Supernormal over 3 yearsNo, it works without anything in addition, at least using bash version 4.3.48