หลีกเลี่ยงข้อผิดพลาดเนื่องจากเครื่องหมายดอกจันที่ไม่ขยาย


16

ในทุบตีฉันมักจะใช้ for-loops ดังต่อไปนี้

for file in *.type; do 
  sommecommand "$file"; 
done;

*.typeในการดำเนินการสำหรับทุกไฟล์ที่ตรงกัน หากไม่พบไฟล์ที่มีจุดจบนี้ในไดเรกทอรีใช้งานเครื่องหมายดอกจันจะไม่ถูกขยายและโดยปกติฉันจะได้รับข้อความแสดงข้อผิดพลาดที่บอกว่า somecommand ไม่พบไฟล์ ฉันสามารถคิดได้ทันทีหลายวิธีเพื่อหลีกเลี่ยงข้อผิดพลาดนี้ แต่การเพิ่มเงื่อนไขก็ไม่ได้ดูสวยงามมากนัก มีวิธีที่สั้นและสะอาดในการบรรลุเป้าหมายนี้หรือไม่?

คำตอบ:


20

ใช่เรียกใช้คำสั่งต่อไปนี้:

shopt -s nullglob

มันจะทำให้การแข่งขันเป็นโมฆะและจะไม่มีข้อผิดพลาดเกิดขึ้น

  • หากคุณต้องการให้พฤติกรรมนี้เป็นค่าเริ่มต้นให้เพิ่มคำสั่งใน ~/.bashrc
  • หากคุณต้องการตรวจสอบ null glob ในเปลือก POSIX ลอง

    for i in *.txt; do
      [ "$i" = '*.txt' ] && [ ! -e '*.txt' ] && continue
    done

ดูhttp://mywiki.wooledge.org/NullGlob


1
โปรดทราบว่าเป็นไปได้ที่จะมีไฟล์ชื่อ*.txtจริง มันจะคุ้มค่าการตรวจสอบว่าไฟล์ที่มีอยู่
Chris Down

โพสต์แก้ไขตามนั้น
Gilles Quenot

หมายเหตุ @ChrisDown ที่แสดงความคิดเห็นเช่นเดียวกับคำตอบของคุณใช้ที่นี่ (กับผลกระทบที่อาจเกิดขึ้นรุนแรงมากขึ้นเพราะการbreakแทนcontinue)
Stéphane Chazelas

6

ในทุบตีคุณสามารถใช้shopt -s nullglobเพื่อขยายไปยังอาร์เรย์ว่างเปล่าหากไม่มีการแข่งขัน

ใน POSIX shells without nullglobคุณสามารถหลีกเลี่ยงปัญหานี้ได้โดยตรวจสอบว่าชื่อไฟล์ที่ส่งผ่านนั้นมีอยู่จริงโดย[ -e "$file" ] || [ -L "$file" ] || continueเป็นส่วนแรกของforลูปของคุณ


1
โปรดทราบว่าจะไม่เทียบเท่าอย่างเคร่งครัดเนื่องจาก[ -eจะส่งคืนค่าเท็จสำหรับไฟล์หรือไฟล์ที่ไม่สามารถเข้าถึงได้ซึ่งมีการเชื่อมโยงไปยังไฟล์ที่ไม่สามารถเข้าถึงได้หรือไม่มีอยู่
Stéphane Chazelas

@StephaneChazelas ให้คะแนนเกี่ยวกับ symlink ได้รับการยอมรับ แต่คุณมีอะไรในใจโดย "ไฟล์ที่ไม่สามารถเข้าถึง" แม้ว่าผมchmod 0 the_file, [ -e the_file ]ยังคงประเมินความจริงดังนั้นจึงต้องอย่างอื่น
dubiousjim

1
ส่งการแก้ไขเพื่อจัดการ symlink ที่ใช้งานไม่ได้ หวังว่าไม่เป็นไร
dubiousjim

2
mkdir -p x/{a,b} && chmod 444 x && echo x/* && [ -e x/a ]@dubiousjim, x / a ไม่สามารถเข้าถึงได้ แต่เนื่องจาก x สามารถอ่านได้ x / * จะขยายออก
Stéphane Chazelas

@ StephanChazelas ยอดเยี่ยมขอบคุณสำหรับการอธิบาย
dubiousjim

4

เทคนิคปกติสำหรับเชลล์ที่ไม่มีnullglobตัวเลือกคือ

set -- [*].type *.type
case $1$2 in
  '[*].type*.type') shift 2;;
  *) shift
esac
for file do
  cmd  -- "$file"
done

พิเศษ[*].typeคือเพื่อครอบคลุมกรณีที่มีหนึ่งไฟล์ที่เรียกว่า*.typeในไดเรกทอรีปัจจุบัน

ตอนนี้ถ้าคุณต้องการที่จะรวมไฟล์จุดที่จะกลายเป็นความซับซ้อนมากขึ้น

ฉันเชื่อว่าเทคนิคนี้ได้รับการประกาศเกียรติคุณจากลอร่าแฟร์เฮดเมื่อไม่กี่ปีที่ผ่านมา


0

find . -name '*.type' -maxdepth 0 -exec somecommand "{}" ";"

สิ่งนี้จะลบforลูปและวงกลมของเชลล์ออกจากสมการทั้งหมด findจะดำเนินการ-execคำสั่งหนึ่งครั้งต่อการแข่งขันและหากไม่มีการแข่งขันมันจะไม่ถูกดำเนินการ -maxdepth 0แนะหาไม่ recurse ลงในไดเรกทอรีย่อยของชื่อเส้นทางอาร์กิวเมนต์ ( .ในกรณีนี้)

ข้อเสียคือมันเกี่ยวข้องกับแอปพลิเคชั่นอื่นแม้ว่าจะมีอยู่ในระบบ Linux แทบทุกระบบ (และอาจเป็น Unixes ส่วนใหญ่เช่นกัน)

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