ลบประเภทไฟล์ทั้งหมดยกเว้นหนึ่งประเภทขึ้นไป


20

ฉันพยายามค้นหาคำสั่งเพื่อลบไฟล์ทั้งหมดในโฟลเดอร์ แต่ไม่ใช่ประเภทไฟล์ แต่ดูเหมือนว่าฉันจะไม่มีโชค สิ่งที่ฉันลองมาแล้ว:

set extended_glob
rm !(*.dmg)
# this returns zsh:number expected

rm ./^*.dmg
# this returns no matches found 

รุ่นของ zsh zsh 5.0.2 (x86_64-apple-darwin13.0.1)ฉันใช้เป็น

คำตอบ:


22

extended_globตัวเลือกที่จะช่วยให้คุณ zsh ของตัวเองขยายไวยากรณ์ glob

setopt extended_glob
rm -- ^*.dmg
rm -- ^*.(dmg|txt)

คุณสามารถตั้งค่าksh_globตัวเลือกที่จะได้รับksh globs ระวังว่าในกรณีทั่วไปที่รูปแบบเชิงลบเป็นสิ่งสุดท้ายในคำ zsh อาจแยกวงเล็บเป็น qualifier glob (มันไม่ได้ทำในโหมดการจำลอง ksh)

setopt ksh_glob
rm -- !(*.dmg|*.txt)
setopt no_bare_glob_qual
rm -- !(*.dmg)

ดูเหมือนจะใช้งานไม่ได้ เมื่อฉันเรียกใช้rm -r secrets/!(directory)มันก็จะถามหาnumber expectedหรือบางครั้งมันก็ทำให้ฉันevent not found: directory
CMCDragonkai

@CMCDragonkai“ คาดว่าจะเป็นตัวเลข” แสดงว่าคุณไม่ได้ตั้งค่าksh_globตัวเลือก “ ไม่พบเหตุการณ์: ไดเรกทอรี” ระบุว่าคุณกำลังใช้ bash (ซึ่งเข้าใจ!(…)ไวยากรณ์ได้ แต่หลังจากนั้นshopt -s extglob)
Gilles 'SO- หยุดความชั่วร้าย'

ฉันจะใช้ bash เมื่อฉันอยู่ในเปลือก zsh ได้อย่างไร
CMCDragonkai

สำหรับฉันsetopt ksh_glob; echo !(a|b)ทำงานในขณะที่setopt ksh_glob; echo !(a)ไม่ได้ ("คาดว่าจะมีจำนวน") ...
ThiefMaster

@ThiefMaster ฉันมีปัญหาเดียวกัน มันเป็นข้อบกพร่องหรือไม่?
CodeTower

5

คุณสามารถใช้findแทนเปลือกของคุณ:

find . -mindepth 1 -maxdepth 1 ! -name "*.dmg" -delete

จากman find:

   ! expr True  if  expr  is false.  This character will also usually need
          protection from interpretation by the shell.
   -name pattern
          Base of file name (the path with the leading directories removed)
          matches shell pattern pattern. 
   -delete
          Delete  files; true if removal succeeded.  If the removal failed,
          an error message is issued.  If -delete fails, find's exit status
          will be nonzero (when  it eventually exits).  Use of -delete 
          automatically turns on the -depth option.

หากคุณไม่สามารถใช้findด้วยเหตุผลใด ๆ นี่เป็นวิธีทำด้วยzsh(หรือกระสุนอื่น ๆ ) zshเป็นzshอาจมีวิธีที่ง่ายของการทำเช่นนี้ แต่เนื่องจากผมเป็นbashคนที่แต่งตัวประหลาดนี้เป็นสิ่งที่ฉันมาด้วย:

for file in *; do if [[ ! "$file" == *.dmg ]]; then rm $file; fi; done

น่าเสียดายที่เมื่อใดก็ตามที่ฉันใช้ find ใน mac ของฉันมันเพิ่งออกจากเซสชัน zsh ปัจจุบันโดยไม่ต้องแจ้งให้ทราบล่วงหน้า คุณมีปัญหาเดียวกันหรือไม่? find [Process completed]
Dzung Nguyen

1
@nXqd findดูคำตอบที่อัปเดตหาวิธีที่จะทำมันได้โดยไม่ต้อง ฉันขอแนะนำให้คุณโพสต์คำถามเกี่ยวกับfindปัญหาของคุณที่ไม่ควรเกิดขึ้น type -a findถ้าคุณทำรวมถึงการส่งออกของ
terdon

1
แม้จะอยู่ในทุบตีมีวิธีที่ง่าย: หลังจากrm !(*.dmg) shopt -s extglob
Gilles 'หยุดความชั่วร้าย'

@terdon ขอบคุณสำหรับเคล็ดลับการดีบักในเชลล์ ผลลัพธ์ที่ได้น่าจะเป็นที่ถูกต้อง:find is a shell function find is /usr/bin/find
Dzung เหงียน

@nXqd /usr/bin/findที่ไม่ถูกต้องก็ไม่ควรจะเป็นฟังก์ชั่นเปลือกก็ควรจะ คุณมีฟังก์ชั่นที่เรียกว่าfindกำหนดไว้ในหนึ่งในไฟล์ bash config ของคุณ เนื่องจากคุณอยู่บน OSX นั่นอาจเป็น~/.profileไปได้
terdon

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.