วิธีกำจัด "ไม่พบที่ตรงกัน" เมื่อเรียกใช้ "rm *"


22

ใช้zshฉันได้รับข้อความ "ไม่พบการจับคู่" เมื่อเลือกรูปแบบที่ไม่เหมาะสมrmและแม้เมื่อเปลี่ยนเส้นทางผลลัพธ์

# rm * > /dev/zero 2>&1
  zsh: no matches found: *

ฉันจะกำจัดข้อความนี้ได้อย่างไร


คุณกำลังพยายามลบทุกสิ่งในไดเรกทอรีปัจจุบันหรือไม่? ไดเรกทอรีปัจจุบันคืออะไร
cutrightjm

คุณสามารถใช้setopt extended_glob(หรือแม้กระทั่งธรรมดาrm * >/dev/null 2>&1) แต่จริงๆคุณควรจะทำเพื่อแก้ปัญหาไม่จำเป็นต้องมีrm *ที่อันตรายทันที
grochmal

คุณควรจะจมลงไปแทนแล้ว/dev/null dev/zeroนอกจากนี้คุณstderrเปลี่ยนเส้นทางหายไป&; 2>&1มันควรจะเป็น
roaima

ข้อความแสดงข้อผิดพลาดถูกสร้างขึ้นโดยzshในระหว่างการประเมินผลของคำสั่งและไม่ใช่ในระหว่างการรันไทม์ของคำสั่งนั้นเอง (เนื่องจากข้อผิดพลาดที่คำสั่งไม่ได้รัน) การเปลี่ยนทิศทางเอาต์พุตที่นี่จะมีผลกับเอาต์พุตของคำสั่งเท่านั้นและไม่ใช่เชลล์เอง
Adaephon

คำตอบ:


42

ลักษณะการทำงานนี้จะถูกควบคุมโดย zsh ของตัวเลือกnomatch ตามค่าเริ่มต้นหากบรรทัดคำสั่งมีนิพจน์แบบกลมซึ่งไม่ตรงกับสิ่งใด Zsh จะพิมพ์ข้อความแสดงข้อผิดพลาดที่คุณเห็นและไม่เรียกใช้คำสั่งเลย คุณสามารถปิดใช้งานสิ่งนี้ได้ด้วยการเรียกใช้

setopt +o nomatch

จากนั้นการแสดงออกแบบกลม ๆ ซึ่งไม่ตรงกับสิ่งใดจะถูกทิ้งให้เป็นอย่างที่เป็นอยู่และคุณจะได้รับข้อความแสดงข้อผิดพลาดจากrm(ซึ่งคุณสามารถปิดการใช้งานได้-fแม้ว่าจะเป็นความคิดที่ไม่ดีเพราะมันจะบังคับให้ลบออก ต้องการที่จะ).


4
พฤติกรรมนี้ยังควบคุมโดยnullglobและcshnullglobตัวเลือก หากnullglobถูกตั้งค่าและไม่พบไฟล์ที่ตรงกันรูปแบบจะถูกลบออกจากรายการอาร์กิวเมนต์แทนการสร้างข้อผิดพลาด การตั้งค่าcshnullglobมีผลคล้ายกันยกเว้นว่ารูปแบบทั้งหมดในคำสั่งไม่มีการจับคู่ซึ่งในกรณีนี้จะมีการรายงานข้อผิดพลาด หมายเหตุ: การตั้งค่าnullglobหรือการแทนที่cshnullglob nomatchนอกจากนี้คุณยังสามารถตั้งค่าnullglobรูปแบบเดียวโดยใช้รอบคัดเลือก glob :N rm *(N)
Adaephon

nomatchน้อยกว่าอุดมคตินั่นคือสิ่งที่เปลือกหอย Bourne ทำ หากรูปแบบไม่ตรงกันจะถูกส่งตาม - คือrm(!) ซึ่งrmจะทำให้เกิดข้อผิดพลาดหรือแย่กว่านั้นสามารถลบไฟล์ที่ไม่ถูกต้องสำหรับรูปแบบเช่น*.[ch]!
Stéphane Chazelas

9

คุณต้องการให้มันทำอะไรแทน ไม่ได้ทำงานrmเลย (1)? ทำงานด้วย*อาร์กิวเมนต์ที่เป็นตัวอักษรในเชลล์ที่เหมือน Bourne (2)? เรียกใช้โดยไม่มีข้อโต้แย้งเลย (3)?

  1. files=(*(N)); (($#files)) && rm -- $files. หรือ(rm -- *) 2> /dev/nullว่าจะซ่อนข้อผิดพลาดของแท้โดยrmที่จะโง่ คุณสามารถละทิ้งzshข้อผิดพลาด แต่คืนค่า stderr สำหรับrmคำสั่งด้วย(rm -- * 2>&3 3>&-) 3>&2 2> /dev/null
  2. emulate sh -c 'rm -- *' 2> /dev/null. จากนั้นเหมือนshที่zshตอนนี้จำลองสำหรับบรรทัดคำสั่งเดียวนั้นการไม่จับคู่*จะถูกส่งผ่านตามที่เป็นอยู่rmและrmบ่นว่า*ไฟล์นั้นไม่มีอยู่ เราปราบปรามrm's stderr เป็นคุณจะทำอย่างไรในshการปราบปรามที่เกิดข้อผิดพลาดอีกครั้ง แต่ที่โง่มันจะซ่อนข้อผิดพลาดของแท้โดยrmเมื่อเทียบกับข้อผิดพลาดที่เกิดขึ้นโดยการกระทำผิดกฎหมายของshการส่งผ่านตัวอักษรเพื่อ* จะไม่บ่นเกี่ยวกับไฟล์ที่ไม่มีอยู่แต่คุณสามารถทำได้rmrm -f '*'*emulate sh -c 'rm -f -- *'
  3. rm -- *(N). rmจะบ่น แต่เมื่อไม่ได้ผ่านการโต้แย้งใด ๆ แต่อีกครั้งไม่:rm -frm -f -- *(N)

โดยทั่วไปrm -fคือคำสั่งที่คุณต้องการใช้หากคุณต้องการให้ไฟล์ทั้งหมดหายไปและได้รับข้อผิดพลาดหากไฟล์ไม่สามารถลบออกได้หรือ IOW ยังคงอยู่ที่นั่นหลังจากrmส่งคืนแล้ว โดยทั่วไปคุณต้องการใช้-fในสคริปต์เพื่อหลีกเลี่ยงผู้ใช้ที่ได้รับแจ้งภายใต้สถานการณ์บางอย่าง

ที่นี่การโทรหาrmเมื่อ glob ไม่ตรงกันไม่ถูกต้อง sh1พฤติกรรมที่ไม่ถูกต้อง มันไม่เป็นอันตรายต่อรูปแบบที่เหมือน*กัน แต่อย่างใดอย่างหนึ่งการ*.[ch]ส่งผ่าน*.[ch]ตามที่เป็นเมื่อไม่ตรงกันอาจทำให้*.[ch]ไฟล์ถูกลบโดยไม่ได้ตั้งใจ:

$ ls
*.[ch]  foo.txt
$ zsh -c 'rm *.[ch]'
zsh:1: no matches found: *.[ch]
$ ls
*.[ch]  foo.txt
$ sh -c 'rm *.[ch]'
$ ls
foo.txt

ความล้มเหลวที่มีข้อผิดพลาดเป็นสิ่งที่เหมาะสมที่สุดที่จะทำและเป็นสิ่งที่zsh(และfish, csh, tcsh, bash -o failglobและเดิมเชลล์ยูนิกซ์) ไม่

และถ้าคุณต้องการที่จะดูแลตัวเองในกรณีพิเศษนั้นzshทำให้มันง่ายขึ้นด้วย(N)คุณสมบัติรอบตัว (สำหรับnoglob ) เช่นในกรณีที่ (1) ด้านบน fish(อย่างน้อยในเวอร์ชันล่าสุด ) ทำให้ง่ายยิ่งขึ้นเนื่องจากทำnoglobโดยนัยสำหรับsetคำสั่ง ดังนั้นสิ่งที่เทียบเท่าจะเป็น:

set files *
if count $files > /dev/null
  rm -f -- $files
end

ดูทำไม nullglob ไม่เริ่มต้นสำหรับรายละเอียดเพิ่มเติม


1 . พูดอย่างเคร่งครัดมันเป็นเพียงแค่shเปลือก Bourne (ตั้งแต่ Unix V7 ในปี 1979); เวอร์ชันก่อนหน้าของsh(ซึ่งเรียก/etc/globใช้ wildcard ที่ไม่ได้กล่าวถึงซึ่งเป็นที่มาของชื่อglob ) ทำตัวเหมือนcshหรือzsh -o cshnullglobว่า/etc/globจะยกเลิกคำสั่งถ้าไม่มี globs ใด ๆ ที่ตรงกัน (และจะระงับ globs ที่ไม่ตรงกันถ้าอย่างน้อย หนึ่งในนั้นมีการแข่งขันใด ๆ ) พฤติกรรมถูกทำลายโดยเชลล์เป้าหมาย


ฉันคิดว่าเขาคาดว่าจะได้รับข้อความแสดงข้อผิดพลาดจากrmและไม่ใช่จากเชลล์ บางอย่างเช่น "rm: ไม่สามารถลบ` * ': ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว "
Emmanuel

@Emmanuel แล้วนั่นคือ 2: emulate sh -c 'rm -- *'เพื่อรับพฤติกรรม (buggy IMO) ของ Bourne shell
Stéphane Chazelas

@Stephane_Chazelas ตามที่เขียนไว้ 2 เป็นคำตอบที่ถูกต้องสำหรับคำถามที่เขาไม่ได้ถาม :)
Emmanuel

@Emmanuel ทั้ง 3 ตอบคำถาม: วิธีกำจัดข้อผิดพลาด "ไม่ตรงกัน" รหัสของ OP ระงับrmข้อผิดพลาด นั่นคือสิ่งที่คุณจะทำในเชลล์อื่น ๆ เพื่อระงับข้อผิดพลาดเมื่อไม่มีไฟล์ที่ตรงกันและทำให้เกิดการปราบปรามข้อผิดพลาด rm ของแท้เช่นกัน คำตอบของฉันแสดงให้เห็นว่าและหวังว่าจะแสดงให้เห็นว่าพฤติกรรม zsh เป็นที่ต้องการได้อย่างไร
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.