如何使cd参数不区分大小写?


9

有时,在访问各种目录时,多数情况下我记得我们Linux系统下目录的名称或至少一部分名称。但是某些目录的名称以大写字母开头或大写字母中间的一个字符开头。

任何人都可以建议我如何才能让下面的参数cd命令不区分大小写,这样,如果我执行cd BackupDirectory或者cd backupdirectory它可以进入该目录名BackupDirectory。

当然,我不想为其他用户搞麻烦,因此,如果上述可行,是否可以将更改仅应用于我正在使用的会话,而不会影响其他用户?

好的,我试过了 set completion-ignore-case,但是这行不通。如果我键入cd bTabEsc Esc它填充目录名而忽略大小写,则只会有所帮助。但是,我需要做的是cd backupdirectory,它只是忽略大小写并BackupDirectory自行输入。


您将如何避免歧义?如果您有backUPbackUp,那么您将backup不希望进入哪个目录?
伯恩哈德

您正在使用哪个外壳?
2013年

您是否考虑过使用类似的工具mc或切换到GUI?使生活更加轻松。
ott--

Answers:


17

启用cdspell将有助于:

shopt -s cdspell

man页面:

cdspell 如果设置,将更正cd命令中目录组件的拼写错误。检查的错误是转置字符,缺少字符以及一个字符太多。如果找到更正,则打印更正的文件名,然后继续执行命令。此选项仅由交互式外壳程序使用。


运行此命令后,您是否需要执行任何操作以使更改生效?
内森·亚瑟

我会这样假设,因为仅输入shopt -s cdspell对我没有任何帮助
sdfsdf

10

重击

set completion-ignore-case on~/.inputrc(或bind 'set completion-ignore-case on'~/.bashrc)将是我的建议。如果要输入全名,为什么不按几次Shift键就不知道呢?

但是,如果您真的想要它,这里有一个包装,cd它尝试进行完全匹配,如果没有,则寻找不区分大小写的匹配,如果唯一则执行匹配。它使用nocaseglobshell选项进行不区分大小写的glob,并通过追加@()(不匹配任何内容,并要求extglob)将参数转换为glob 。extglob定义函数时必须打开该选项,否则bash甚至无法解析它。此功能不支持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
}

sh

当我在使用它时,这是ksh93的类似功能。该~(i)修改为不区分大小写的匹配似乎是不兼容的/后缀来只匹配目录(这可能是我在KSH释放的错误)。因此,我使用另一种策略来清除非目录。

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[@]}"
}

sh

最后,这是zsh版本。同样,允许不区分大小写的完成可能是最好的选择。如果没有精确的大小写匹配,则以下设置将退回到不区分大小写的状态:

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

删除''以显示所有不区分大小写的匹配项,即使存在完全区分大小写的匹配项也是如此。您可以从的菜单界面进行设置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
这很棒。但是您需要添加它才能inputrc使其正常工作。像这样:echo "set completion-ignore-case on" >> ~/.inputrc
jsejcksn

@JesseJackson是的,这在这里是隐含的,因为询问者已经知道,但是我会将其添加到我的答案中以供将来的访问者使用。
吉尔(Gilles)'所以

尝试与此一起使用cd时出现以下错误:(cd:cd:17: no such file or directory: videos我的目录名为Videos
Sridhar Sarnobat

@ user7000哪个版本,在哪个shell下?
吉尔(Gilles)'所以

1
@ user7000在zsh 5.0.7下为我工作。也许您已经设置了一个选项,可以更改全局工作方式?如果您更改emulate -L zsh为,有帮助emulate -LR zsh吗?(通过我刚刚修复的错误的方式,应该是emulate -L zsh,不是emulate zsh,否则它会弄乱您的shell选项。)
Gilles'SO-别再作恶了
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.