วิธีการทำกรณีที่มีข้อโต้แย้งซีดีไม่สำคัญ?


9

บางครั้งในขณะที่เข้าถึงไดเรกทอรีต่างๆมันเกิดขึ้นส่วนใหญ่เวลาที่ฉันจำชื่อหรืออย่างน้อยส่วนหนึ่งของชื่อของไดเรกทอรีภายใต้ระบบ Linux ของเรา แต่บางไดเรกทอรีมีชื่อเริ่มต้นด้วยตัวอักษรตัวแรกหรือหนึ่งในตัวละครที่อยู่ตรงกลางของชื่อตัวพิมพ์ใหญ่

ใครสามารถแนะนำฉันจะทำให้ข้อโต้แย้งดังต่อไปนี้cdกรณีคำสั่ง INSENSITIVE เช่นว่าถ้าฉันทำcd BackupDirectoryหรือcd backupdirectoryมันสามารถป้อนชื่อไดเรกทอรี BackupDirectory

แน่นอนว่าฉันไม่ต้องการควงสิ่งต่าง ๆ สำหรับผู้ใช้รายอื่นดังนั้นหากเป็นไปได้ข้างต้นเป็นไปได้หรือไม่ว่าการเปลี่ยนแปลงนั้นสามารถนำไปใช้กับเซสชันที่ฉันกำลังใช้และไม่ส่งผลกระทบต่อผู้ใช้คนอื่น ๆ ?

ตกลงฉันพยายาม set completion-ignore-caseแต่ก็ไม่ได้ผล มันช่วยได้ถ้าฉันพิมพ์cd bและTabหรือEsc Escเติมชื่อไดเรกทอรีโดยไม่สนใจขนาดตัวพิมพ์ แต่สิ่งที่ฉันต้องการคือถ้าฉันทำcd backupdirectoryมันก็แค่เพิกเฉยต่อคดีและเข้าไปBackupDirectoryในตัวของมันเอง


คุณจะหลีกเลี่ยงความคลุมเครือได้อย่างไร หากคุณมีbackUPและbackUpจะbackupไม่มีไดเรกทอรีใดที่คุณต้องการไป
Bernhard

คุณใช้เปลือกไหน
Gert van den Berg

คุณได้พิจารณาใช้เครื่องมือเช่นmcหรือเปลี่ยนเป็น GUI หรือไม่? ทำให้ชีวิตง่ายขึ้นมาก
ott--

คำตอบ:


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ที่พยายามจับคู่แบบตรงและถ้าไม่มีก็จะมองหาการแข่งขันแบบตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ถ้ามันไม่ซ้ำกัน มันใช้nocaseglobตัวเลือกเชลล์สำหรับการวนตัวพิมพ์แบบไม่คำนึงถึงขนาดตัวพิมพ์และเปลี่ยนการโต้แย้งให้เป็นแบบกลมโดยต่อท้าย@()(ซึ่งไม่ตรงกับสิ่งใดและต้องการextglob) extglobตัวเลือกที่จะต้องมีการเปิดใช้งานเมื่อกำหนดฟังก์ชั่นมิฉะนั้นทุบตีไม่สามารถแม้แต่จะแยกมัน 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

ในขณะที่ฉันอยู่ที่นี่นี่เป็นฟังก์ชั่นที่คล้ายกันสำหรับ ksh93 การ~(i)จับคู่แบบ case-insensitive ที่แก้ไขแล้วดูเหมือนจะไม่เข้ากันกับ/ส่วนต่อท้ายเพื่อจับคู่ไดเรกทอรีเท่านั้น (นี่อาจเป็นข้อผิดพลาดในการปล่อย 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
}

1
มันเยี่ยมมาก แต่คุณจะต้องเพิ่มมันเพื่อinputrcให้มันใช้งานได้ เช่นนี้:echo "set completion-ignore-case on" >> ~/.inputrc
jsejcksn

@JesseJackson ใช่นั่นเป็นนัยที่นี่เพราะผู้ถามรู้อยู่แล้ว แต่ฉันจะเพิ่มคำตอบของฉันสำหรับผู้เยี่ยมชมในอนาคต
Gilles 'หยุดความชั่วร้าย'

ฉันได้รับข้อผิดพลาดต่อไปนี้เมื่อพยายามใช้ cd กับสิ่งนี้: cd:cd:17: no such file or directory: videos(ฉันมี dir ที่เรียกว่าVideos)
Sridhar Sarnobat

@ user7000 รุ่นใดภายใต้เชลล์ใด
Gilles 'หยุดชั่วร้าย'

1
@ user7000 ใช้งานได้กับฉันภายใต้ zsh 5.0.7 บางทีคุณอาจตั้งค่าตัวเลือกที่เปลี่ยนวิธีการทำงานแบบกลม ๆ ? มันช่วยได้ถ้าคุณเปลี่ยนemulate -L zshเป็นemulate -LR zsh? (โดยที่ฉันเพิ่งแก้ไขข้อผิดพลาดที่ควรจะเป็นemulate -L zshไม่emulate zshเช่นนั้นมันจะทำให้ตัวเลือกเชลล์ของคุณยุ่งเหยิง)
Gilles 'ดังนั้น - หยุดความชั่วร้าย'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.