ฉันคาดหวังว่าจะไม่ได้รับผลลัพธ์ใด ๆ
หาก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
(การตั้งค่ามาตรฐาน) จะให้รูปแบบตัวเอง