Bash

如何使 cd 參數不區分大小寫?

  • January 19, 2022

有時在訪問各種目錄時,大多數時候我都會記住我們 Linux 系統下目錄的名稱或至少部分名稱。但是某些目錄的命名以第一個字元大寫或名稱中間的一個字元大寫開頭。

任何人都可以建議我如何在cd命令案例 INSENSITIVE 之後設置參數,這樣如果我執行cd BackupDirectory或者cd backupdirectory它可以輸入目錄名稱 BackupDirectory。

當然,我不想為其他使用者搞砸事情,所以如果上述情況可行,是否有可能將更改僅應用於我正在使用的會話並且不會影響其他使用者?

好的,我試過 set completion-ignore-case了,但這不起作用。如果我鍵入cd bTab/或Esc Esc它填充目錄名稱而忽略大小寫,它只會有所幫助。但是,我需要的是,如果我執行 a cd backupdirectory,它只會忽略大小寫並BackupDirectory自行進入。

啟用cdspell將有助於:

shopt -s cdspell

man頁面:

cdspell 如果設置,將糾正 cd 命令中目錄組件拼寫的小錯誤。檢查的錯誤是轉置字元、缺少字元和一個字元太多。如果找到更正,則列印更正的文件名,然後繼續執行命令。此選項僅由互動式 shell 使用。

重擊

set completion-ignore-case onin ~/.inputrc(或bind 'set completion-ignore-case on'in ~/.bashrc)將是我的建議。如果您要輸入全名,為什麼要按幾下Shift鍵?

但是如果你真的想要它,這裡有一個包裝器,cd它會嘗試精確匹配,如果沒有,則查找不區分大小寫的匹配並在它唯一時執行它。它使用nocaseglobshell 選項進行不區分大小寫的 globbing,並通過附加將參數轉換為 glob @()(不匹配任何內容,並且需要extglob)。定義函式時該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
}

克什

雖然我在這裡,但這裡有一個類似的 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[@]}"
}

Zsh

最後,這是一個 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
}

引用自:https://unix.stackexchange.com/questions/60162