Nullglob डिफ़ॉल्ट क्यों नहीं है?


61

अधिकांश गोले nullglobमें डिफ़ॉल्ट नहीं है। उदाहरण के लिए, यदि आप इस कमांड को चलाते हैं

ls *

खाली निर्देशिका में, यह तर्कों की एक खाली सूची के बजाय, *शाब्दिक को शाब्दिक रूप से विस्तारित करेगा *। उस व्यवहार को बदलने के तरीके हैं, ताकि *एक खाली निर्देशिका में तर्कों की एक खाली सूची वापस आ जाएगी, जो अधिक सहज प्रतीत होगी।

तो, क्या nullglobडिफ़ॉल्ट रूप से अक्षम होने का एक कारण है? यदि हां, तो वह कारण क्या है?


13
किसी ने एक बार एक बुरा विकल्प बनाया जो "हमने हमेशा इसे इस तरह से किया है" में बदल गया। सॉफ्टवेयर की दुनिया में एक बहुत ही सर्वव्यापी घटना (न केवल)।
PSkocik

4
मूल कारण यह है कि नलग्लोब विकल्प वापस मौजूद नहीं था। तो पीछे की संगतता बनाए रखने के लिए इसे डिफ़ॉल्ट रूप से अक्षम किया जाना चाहिए।
पीएम 2

3
हालांकि यह विशेष रूप से अशक्त ग्लोब का उल्लेख नहीं करता है, ग्लोबिंग
StrongBad

4
मुझे लगता है कि कुछ लोगों को लगता है कि यह स्पष्ट होना चाहिए कि nullglob डिफ़ॉल्ट रूप से सक्षम होना चाहिए। मुझे नहीं लगता कि यह स्पष्ट है। कमांड इंवोकेशन से पहले शेल का विस्तार होता है, इसका मतलब है कि कुछ भी नहीं विस्तारित होना ग्लोब के अपरिवर्तित रहने की तुलना में कम सहज व्यवहार है।
कोजीरो

2
@kojiro किसके लिए कम सहज? * NIX गोले के साथ किसी भी परिचित व्यक्ति को पता है कि *एक गोला है और सभी मौजूदा फ़ाइलों को विस्तारित करता है; एक विशेष मामले के लिए यह "सहज" कैसे है जहां खाली निर्देशिका ग्लब्स को शाब्दिक रूप से "विस्तारित" किया जाता है *?
काइल स्ट्रैंड

जवाबों:


78

nullglobविकल्प (जो BTW एक है zshआविष्कार, केवल करने के लिए साल बाद जोड़ा bash( 2.0मामलों की संख्या में आदर्श नहीं होगा))। और lsएक अच्छा उदाहरण है:

ls *.txt

या इसके अधिक सही समकक्ष:

ls -- *.txt

साथ nullglobपर चलाना शामिल है lsकोई तर्क जो माना जाता है के साथ ls -- .(वर्तमान निर्देशिका की सूची) यदि कोई फ़ाइल से मेल खाते हैं, जो शायद बुला से भी बदतर है lsएक शाब्दिक साथ *.txtतर्क के रूप में।

आपको अधिकांश पाठ उपयोगिताओं के साथ समान समस्याएं होंगी:

grep foo *.txt

fooअगर कोई txtफ़ाइल नहीं है, तो स्टड पर खोज करेंगे ।

एक अधिक समझदार डिफ़ॉल्ट, और csh, tsh, zsh या मछली 2.3+ (और शुरुआती यूनिक्स गोले) में से एक पूरी तरह से कमांड को रद्द करना है यदि ग्लोब मेल नहीं खाता है।

bash(चूंकि संस्करण 3) में इसके लिए एक failglobविकल्प है (इस चर्चा के लिए दिलचस्प ash, एटी एंड टी के विपरीत kshया zsh, bashविकल्पों के लिए स्थानीय स्कोप का समर्थन नहीं करता है (हालांकि यह 4.4 में बदलना है), वह विकल्प जब वैश्विक स्तर पर सक्षम होता है तो कुछ चीजें टूट जाती हैं बाश-पूर्ण कार्यों की तरह)।

ध्यान दें कि csh और tshsh से भिन्न हैं zsh, fishया bash -O failglobजैसे मामलों में:

ls -- *.txt *.html

जहाँ आपको कमांड को रद्द करने के लिए सभी ग्लोब को मैच नहीं करने की आवश्यकता है। उदाहरण के लिए, यदि एक txt फ़ाइल और कोई html फ़ाइल नहीं है, तो वह बन जाती है:

ls -- file.txt

आप के साथ जो व्यवहार प्राप्त कर सकते हैं zshसाथ setopt cshnullglobही यह में करने के लिए एक अधिक समझदार रास्ते zshकी तरह एक ग्लोब उपयोग करने के लिए होगा:

ls -- *.(txt|html)

में zshऔर ksh93, आप भी आवेदन कर सकते हैं nullglob एक प्रति ग्लोब आधार है, जो एक वैश्विक सेटिंग को संशोधित करने की तुलना में बहुत saner दृष्टिकोण है पर:

files=(*.txt(N))  # zsh
files=(~(N)*.txt) # ksh93

यदि कोई txtफ़ाइल त्रुटि के साथ कमांड को विफल करने के बजाय (या इसे *.txtअन्य शेल के साथ एक शाब्दिक तर्क के साथ एक सरणी बना रही है) तो एक खाली सरणी बनाएगा ।

fish2.3 से पहले के संस्करण इस तरह काम करते हैं bash -O nullglobलेकिन जब एक ग्लोब का कोई मुकाबला नहीं होता है तो इंटरेक्टिव होने पर चेतावनी देते हैं। 2.3 के बाद से, यह zshग्लब्स को छोड़कर for, setया में इस्तेमाल किए गए की तरह काम करता है count

अब, इतिहास नोट पर, व्यवहार वास्तव में बॉर्न शेल द्वारा तोड़ दिया गया था । यूनिक्स के पूर्व संस्करणों में, ग्लोबिंग /etc/globसहायक के माध्यम से किया गया था और सहायक ने ऐसा व्यवहार किया था csh: यह कमांड को विफल कर देगा यदि कोई भी ग्लोब किसी भी फाइल से मेल नहीं खाता और ग्लब्स को बिना किसी मैच के हटा दें।

तो आज हम जिस स्थिति में हैं, वह बॉर्न शेल में किए गए एक बुरे निर्णय के कारण है।

ध्यान दें कि बॉर्न शेल (और सी शेल) एक और नई यूनिक्स सुविधा के साथ आया था: पर्यावरण। इसका मतलब था कि वैरिएबल एक्सपेंशन (यह पूर्ववर्ती ही था $1, $2... स्थितिगत मापदंडों)। बॉर्न शेल ने कमांड प्रतिस्थापन भी पेश किया।

बॉर्न शेल का एक और खराब डिज़ाइन निर्णय चर और कमांड प्रतिस्थापन के विस्तार पर ग्लोबिंग (और विभाजन) करना था (संभवतः थॉम्पसन शेल के साथ पिछड़े संगतता के लिए जहां echo $1अभी भी सम्मिलित होगा /etc/globअगर $1इसमें वाइल्डकार्ड शामिल थे (यह पूर्व प्रोसेसर मैक्रो विस्तार की तरह था) वहाँ, जैसा कि विस्तारित मूल्य में शेल कोड के रूप में फिर से पार्स किया गया था))।

मेल नहीं खाने वाले ग्लब्स का उदाहरण होगा कि:

pattern='a.*b'
grep $pattern file

कमांड को विफल कर देगा (जब तक a.whateverbकि वर्तमान निर्देशिका में कुछ फाइलें नहीं हैं )। csh(जो परिवर्तनशील विस्तार पर ग्लोबिंग भी करता है) उस मामले में कमांड को विफल नहीं करता है (और मैं यह तर्क दूंगा कि वहां एक निष्क्रिय बग छोड़ने से बेहतर है, भले ही यह उतना अच्छा न हो जितना ग्लोबिंग बिल्कुल भी नहीं है zsh)।


एक और प्रयोग करने योग्य समस्या है: nullglobटैब-पूर्णता को तोड़ने के लिए प्रकट होता है (जब यह सक्षम होता है तब टैब कुंजी को दबाने से कुछ नहीं होता है)।
काइल स्ट्रैंड

1
बैश के साथ प्रति ग्लोब के आधार पर नलग्लोब का उपयोग करना संभव है - हालांकि सिंटैक्स ज़ीश जितना सुंदर नहीं हैfiles=$(shopt -s nullglob;echo *.txt)
जॉन

2
@JonNalley, जो फ़ाइल नामों के संगति (स्थान के साथ xpg_echo) को एक स्केलर चर में (संभव परिवर्तन के साथ ) संग्रहीत करता है । आपको मनमाने फ़ाइल नामों के साथ प्रयोग करने योग्य होने के लिए 4.4 या उससे ऊपर या GNU के readarray -td '' files < <(shopt -s nullglob; printf '%s\0' *.txt)साथ कुछ चाहिए। या, अभी भी bash4.4 के साथ, विकल्पों के लिए एक स्थानीय गुंजाइश के लिए एक सहायक फ़ंक्शन का उपयोग करें (25 साल बाद राख से कॉपी)। bash(shopt -s nullglob; printf '%s\0' *.txt) | xargs -r0 cmdxargslocal -
स्टीफन चेजालस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.