ฉันคาดหวังว่าจะไม่ได้รับผลลัพธ์ใด ๆ
หากnullglobมีการเริ่มต้นคำสั่งจำนวนมากจะมีพฤติกรรมค่อนข้างไม่คาดคิดเพราะมันเป็น (อาจจะโชคร้าย) ทั่วไปที่คำสั่งรักษากรณีของศูนย์การขัดแย้งชื่อไฟล์ในทางที่แตกต่างกันในเชิงคุณภาพมากกว่ากรณีของหนึ่งหรือมากกว่าหนึ่งข้อโต้แย้งชื่อไฟล์
สมมติว่าคุณได้เปิดใช้งานnullglob( shopt -s nullglob) *.txtและคุณอยู่ในไดเรกทอรีที่ไฟล์ไม่ตรงกับ จากนั้น*.txtจะขยายเป็นไม่มีอะไร - ไม่ใช่ฟิลด์ว่างเปล่า แต่ไม่มีฟิลด์เลย - ตามที่คุณคาดไว้ แต่นั่นจะมีผลลัพธ์เหล่านี้:
ls *.txtจะรายการทุกไฟล์ในไดเรกทอรีปัจจุบัน (ยกเว้นไฟล์ที่ซ่อนอยู่) เพราะนั่นคือสิ่งที่lsไม่เมื่อคุณไม่ผ่านมันอาร์กิวเมนต์ชื่อไฟล์ใด ๆ
cat *.txtจะอ่านจากอินพุตมาตรฐานเพราะเมื่อไม่มีข้อโต้แย้งชื่อไฟล์ก็เป็นถ้าคุณวิ่งcat cat -หากทำงานแบบโต้ตอบมันจะนั่งรออินพุต คำสั่งหลายตัวทำงานในลักษณะนี้
cp *.txt dest/cp: missing destination file operand after 'dest/'จะล้มเหลวด้วยข้อผิดพลาด นี่ไม่ใช่ภัยพิบัติ แต่มันค่อนข้างสับสนและแตกต่างจากความสำเร็จเงียบ ๆ ที่อาจเป็นที่ต้องการ
file *.txtและโปรแกรมอื่น ๆ ที่ไม่มีลักษณะพิเศษสำหรับกรณีของอาร์กิวเมนต์ชื่อไฟล์ที่เป็นศูนย์จะยังคงล้มเหลวพร้อมกับข้อผิดพลาดหรือข้อความการใช้งานเมื่อไม่มีการส่งผ่าน
- แม้แต่กรณีที่รู้สึกว่าพวกเขาควรจะทำงานบ่อยๆ
printf 'Got file: "%s"\n' *.txtจะพิมพ์Got file: ""แทนไม่มีอะไร
- ความล้มเหลวไม่ได้ตั้งใจที่จะพูดการเกิดขึ้นของ
*, ?และ[ที่ไม่ได้ตั้งใจที่จะขยายได้โดยเปลือกจะมากขึ้นมักจะก่อให้เกิดผลที่ไม่ถูกต้องอย่างเห็นได้ชัด แต่ในรูปแบบที่อาจจะยากที่จะคิดออก ตัวอย่างเช่นถ้าชื่อไฟล์ในไดเรกทอรีปัจจุบันไม่มีการเริ่มต้นด้วยgeditแล้วapt list gedit*(ซึ่งapt list 'gedit*'ก็ตั้งใจ) จะกลายเป็นเพียงapt listและรายชื่อทุกแพคเกจใช้ได้
ดังนั้นจึงเป็นเรื่องดีที่คุณจะไม่ได้รับพฤติกรรมนี้โดยไม่ได้ขอมัน อาจจะมากที่สุดสถานการณ์จริงทั่วไปที่มีความเรียบง่ายจริงโดยมีnullglob for f in *.txtดูคำถามนี้ด้วย ( คำตอบของ Sergiy Kolodyazhnyyเชื่อมโยงกับ)
คำถามที่ยากที่จะตอบคือทำไมfailglob- ทุกที่มันเป็นข้อผิดพลาดในการขยายตัวเพื่อให้มี glob ที่ไม่ตรงกับไฟล์ใด ๆ - ไม่ใช่ค่าเริ่มต้นในการทุบตี ฉันเชื่อว่าคำตอบของ Sergiy Kolodyazhnyyสามารถจับเหตุผลได้แม้ว่าจะไม่ได้กล่าวถึงโดยตรงก็ตาม การรักษา globs ที่ไม่ขยายตัวโดยไม่ก่อให้เกิดข้อผิดพลาดในการขยายตัว (อาจเป็นเรื่องที่น่าเสียดาย) คือพฤติกรรมที่เป็นมาตรฐานและเป็นพฤติกรรมปกติ แม้ว่า bash จะไม่พยายามทำตาม POSIX อย่างสมบูรณ์เว้นแต่ว่ามันถูกเรียกด้วยชื่อshหรือผ่าน--posixตัวเลือก แต่ตัวเลือกการออกแบบจำนวนมากถึงแม้ว่าจะไม่ได้อยู่ในโหมด POSIX ก็ตาม POSIX โดยตรง พวกเขาต้องเลือกพฤติกรรมบางอย่างและมีข้อเสียที่เกี่ยวข้องกับการขัดต่อความคาดหวังของผู้ใช้
ฉันคิดว่านี่เป็นแง่มุมที่มีอิทธิพลน้อยที่สุดในประวัติศาสตร์ของเรื่องดังนั้นฉันจึงบันทึกไว้ในที่สุด ... แต่มันก็คุ้มค่าที่จะพูดถึงว่ามีบางอย่างที่แปลก ๆ เกี่ยวกับnullglobพฤติกรรม
nullglobดูเหมือนสง่างามในตอนแรกเพราะsyntacticallyมันปฏิบัติต่อกรณีของการจับคู่ไฟล์ศูนย์ไม่แตกต่างจากกรณีของหนึ่งสองหรือหมายเลขอื่น ๆ คำสั่งที่เราเรียกใช้ซึ่ง globs ขยายเป็นข้อโต้แย้งสำหรับไม่ได้มีแนวโน้มที่จะปฏิบัติต่อพวกเขาเหมือนกันตามรายละเอียดข้างต้น แต่อย่างน้อยก็รู้สึกถูกต้องทาง syntactically ซึ่งฉันคิดว่าเป็นแรงจูงใจสำหรับคำถามของคุณ
และยังมีความไม่ลงรอยกันที่ลึกซึ้งยิ่งขึ้นอีกหนึ่งอย่างที่nullglobไม่ได้กล่าวถึง กรณีของอักขระศูนย์แบบวงกลม ("อักขระตัวแทน") จะถือว่าแตกต่างอย่างมากจากที่หนึ่งหรือสองหรือหมายเลขอื่น ๆ ตัวอย่างเช่นshopt -s nullglobหากab?d?fไม่ตรงกับไฟล์ใด ๆ ไฟล์นั้นจะถูกลบออก หากab?dไม่ตรงกับไฟล์ใด ๆ ไฟล์นั้นจะถูกลบออก แต่หากabไม่ตรงกับไฟล์ใด ๆ (เช่นหากไม่มีไฟล์ที่มีชื่อตรงab) ไฟล์นั้นจะยังไม่ถูกลบ แน่นอนว่ามันจะเป็นความหายนะถ้ามันถูกลบออกไปเพราะมันอาจไม่ได้ตั้งใจที่จะอ้างถึงไฟล์ที่มีอยู่ในไดเรกทอรีปัจจุบันเลย มันอาจไม่ได้อ้างถึงไฟล์ แต่สิ่งนี้ยังช่วยขจัดความหวังใด ๆ เพื่อความมั่นคงโดยรวม
สามพฤติกรรมทุบตีให้ - เริ่มต้นของการรักษา globs ที่ไม่ตรงกับไฟล์ใด ๆ ราวกับว่าพวกเขาไม่ได้ globs และผ่านพวกเขาไม่ได้ขยายพฤติกรรมที่คุณคาดว่าจะรักษาพวกเขา (ถ้าคุณจะให้อภัยวลีแปลก ๆ นี้) ในฐานะที่บ่งบอกถึงศูนย์ทั้งหมดของไฟล์ที่จับคู่ ( nullglob) และพฤติกรรมที่ปลอดภัยในการพิจารณาข้อผิดพลาด ( failglob) - ทั้งหมดเป็นตัวแทนของวิธีการที่แตกต่างกันไปสู่ความคลุมเครือในเชลล์ไม่สามารถรู้ได้ว่าคำใด ๆ ชื่อไฟล์. เชลล์ทำการขยายโดยไม่มีความรู้ว่าคำสั่งเฉพาะที่คุณเรียกใช้นั้นจะจัดการกับอาร์กิวเมนต์อย่างไร
นี้เป็นหนึ่งในหลาย ๆ กรณีของการแยกของความกังวล ในระบบที่มีการออกแบบตามปรัชญา Unix, แต่ละส่วนมีวัตถุประสงค์เพื่อทำสิ่งหนึ่งและทำมันได้ดี เชลล์ประมวลผลข้อความเป็นคำสั่งและอาร์กิวเมนต์และเรียกใช้คำสั่งเหล่านั้นซึ่งส่วนใหญ่อยู่ภายนอกเชลล์เอง นี้มีแนวโน้มที่จะดีกว่ามากและอื่น ๆ อีกหลากหลายกว่าระบบที่คำสั่งภายนอกเป็นตัวเองรับผิดชอบสำหรับการดำเนินการเปลี่ยนแปลงเหล่านั้น (เช่นเดียวกับการประมวลผลคำสั่งแบบดั้งเดิมใน DOS และ Windows) แต่มันก็มีข้อเสียเป็นครั้งคราว
shopt -s nullglobจะให้สตริงที่ว่างสำหรับรูปแบบที่ไม่ตรงกันและshopt -u nullglob(การตั้งค่ามาตรฐาน) จะให้รูปแบบตัวเอง