यदि .txt फ़ाइल मौजूद नहीं है, तो शेल में * .txt का विस्तार काम नहीं करता है


10

मैं विस्तार के साथ खेल रहा था, और मैंने एक अजीब व्यवहार देखा। मैंने करने की कोशिश की:

echo ./*.txt

और मेरे पास अपनी वर्तमान निर्देशिका में कोई .txt फ़ाइल नहीं थी। मुझे जो आउटपुट मिला वह था:

./*.txt

मैं बस उत्सुक हूं: मुझे यह क्यों मिला? मैं उम्मीद कर रहा था कि मुझे कोई आउटपुट नहीं मिलेगा।

पुनश्च: जब मेरे पास एक .txtफ़ाइल थी, तो विस्तार से सही व्याख्या की गई थी। दूसरे शब्दों में, कहो कि मेरे पास एक फ़ाइल थी, smthn.txtगूंज वास्तव में गूँजती थी current_directory/smthn.txt

जवाबों:


15

बैश शेल मैन पेज से अनुकूलन,

bash प्रत्येक शब्द को अक्षर *,; और [के लिए स्कैन करता है। यदि इन वर्णों में से एक दिखाई देता है, तो शब्द को एक पैटर्न के रूप में माना जाता है, और पैटर्न से मेल खाने वाले फ़ाइलनामों की वर्णानुक्रमिक क्रमबद्ध सूची के साथ प्रतिस्थापित किया जाता है। यदि कोई मिलान फ़ाइल नाम नहीं मिला है, और शेल विकल्प nullglob सक्षम नहीं है, तो शब्द अपरिवर्तित छोड़ दिया जाता है। यदि नलग्लोब विकल्प सेट किया गया है, और कोई मिलान नहीं मिला है, तो शब्द हटा दिया गया है।

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


2
आप इस प्रकार व्यवहार को बदल सकते हैं: shopt -s nullglobबेजोड़ पैटर्न के लिए खाली तार निकलेगा और shopt -u nullglob(मानक सेटिंग) पैटर्न को ही उत्पन्न करेगा।
पर्लडक

13

मैं उम्मीद कर रहा था कि मुझे कोई आउटपुट नहीं मिलेगा।

यदि 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इस प्रश्न को भी देखें (जो सर्जियो कोलोडियाज़नी के उत्तर से जुड़ा हुआ है)।

इसका उत्तर देने के लिए कठिन प्रश्न failglobयह है कि - यह एक ग्लोब को बढ़ाने के लिए एक विस्तार त्रुटि है जो किसी भी फाइल से मेल नहीं खाती - बैश में डिफ़ॉल्ट नहीं है। मेरा मानना ​​है कि सर्गी कोलोडियाज़नी का जवाब सीधे-सीधे इसे संबोधित किए बिना भी इसका कारण है। विस्तार त्रुटि पैदा किए बिना unexpanding ग्लब्स को बनाए रखना (शायद दुर्भाग्य से) मानकीकृत व्यवहार है, और यह पारंपरिक भी है, और इस प्रकार अपेक्षित व्यवहार है। हालांकि बैश पूरी तरह से पॉसिंक-अनुरूप होने का प्रयास नहीं करता है जब तक कि यह नाम के साथ नहीं लगाया जाता है shया --posixविकल्प पारित नहीं किया जाता है, इसके कई डिज़ाइन विकल्प तब भी जब POSIX मोड में सीधे POSIX का पालन नहीं होता है। उन्हें कुछ व्यवहार करना पड़ा, और उपयोगकर्ताओं की उम्मीदों के खिलाफ जाने से जुड़े डाउनसाइड्स हैं।


मुझे लगता है कि यह इस मामले का कम से कम ऐतिहासिक रूप से प्रभावशाली पहलू है इसलिए मैंने इसे अंतिम रूप से सहेजा है ... लेकिन यह ध्यान देने योग्य है कि nullglobव्यवहार के बारे में कुछ वैचारिक रूप से कुछ अजीब है।

nullglobपहली बार में सुरुचिपूर्ण लगता है क्योंकि, वाक्यात्मक रूप से , यह शून्य मिलान फ़ाइलों के मामले को एक, दो या किसी अन्य संख्या के मामले से अलग नहीं करता है। हम जो कमांड चलाते हैं, जो ग्लोब के लिए तर्कों में विस्तार करते हैं, ऊपर बताए अनुसार उनका इलाज नहीं करते हैं। लेकिन वाक्यात्मक रूप से यह कम से कम सही लगता है, जो मुझे लगता है कि आपके प्रश्न के लिए प्रेरणा है।

और फिर भी, एक और, अधिक सूक्ष्म असंगति है जो nullglobसंबोधित नहीं करता है - कि यह वास्तव में बढ़ जाता है। शून्य ग्लोबिंग वर्ण ("वाइल्डकार्ड") के मामले को एक, या दो, या किसी अन्य संख्या से गहराई से अलग तरीके से व्यवहार किया जाता है। उदाहरण के लिए, shopt -s nullglobयदि, ab?d?fकिसी फाइल से मेल नहीं खाता है , तो उसे हटा दिया जाता है; अगर ab?dयह किसी भी फाइल से मेल नहीं खाता है, तो इसे हटा दिया जाता है; लेकिन अगर abवह किसी भी फाइल से मेल नहीं खाता (यानी, अगर कोई फाइल नहीं है जिसका नाम ठीक है ab) तो भी उसे हटाया नहीं जाता है। बेशक, अगर इसे हटा दिया जाता है तो यह एक आपदा होगी, क्योंकि यह मौजूदा निर्देशिका में किसी मौजूदा फ़ाइल को संदर्भित करने का इरादा नहीं हो सकता है; हो सकता है कि वह किसी फ़ाइल का संदर्भ भी न दे। लेकिन यह अभी भी कुल स्थिरता के लिए किसी भी उम्मीद को खत्म करता है।

तीन बर्ताव प्रदान करने वाले बैश प्रदान करता है - ग्लब्स के उपचार का डिफ़ॉल्ट जो किसी भी फाइल से मेल नहीं खाता है, जैसे कि वे ग्लब्स नहीं थे और उन्हें अनएक्सपेन्डेड पास कर रहे थे, व्यवहार जो आप उनसे इलाज की उम्मीद करते थे (यदि आप वाक्यांश के इस विषम मोड़ को क्षमा कर देंगे) मेल करने वाली फ़ाइलों के सभी शून्य को इंगित करने के रूप में ( nullglob), और उन्हें त्रुटियों पर विचार करने का सुरक्षित व्यवहार ( failglob) - सभी शेल में निहित अस्पष्टता के लिए अलग-अलग दृष्टिकोणों का प्रतिनिधित्व करते हैं, यह जानने में सक्षम नहीं हैं कि क्या कोई विशेष शब्द एक होने का इरादा है फ़ाइल का नाम। शेल अपने विस्तार को इस बात के ज्ञान के बिना करता है कि आप इसके साथ विशेष कमांड कैसे कॉल करते हैं, उनके तर्कों का इलाज करेंगे।

यह चिंताओं के अलगाव के कई उदाहरणों में से एक है । उन प्रणालियों में जिनका डिज़ाइन यूनिक्स दर्शन का अनुसरण करता है, प्रत्येक भाग का उद्देश्य एक काम करना और इसे अच्छी तरह से करना है । शेल पाठ को आदेशों और तर्कों में संसाधित करता है और उन आदेशों को आमंत्रित करता है, जिनमें से अधिकांश शेल के लिए बाहरी हैं। यह उन व्यवस्थाओं की तुलना में बहुत अच्छा और अधिक बहुमुखी है जहां बाहरी कमांड खुद उन परिवर्तनों (डॉस और विंडोज में पारंपरिक कमांड प्रोसेसर के साथ) के प्रदर्शन के लिए जिम्मेदार हैं । लेकिन इसकी कभी-कभार गिरावट होती है।


जाहिरा तौर पर, bash-4.3.39 (2) नहीं है failglob। इसलिए यह डिफ़ॉल्ट नहीं हो सकता क्योंकि यह हमेशा समर्थित नहीं है।
रुस्लान

6

इसका मुख्य कारण यह है कि यह POSIX द्वारा निर्दिष्ट मानक व्यवहार है - वह मानक जो शेल कमांड लैंग्वेज को कवर करता है और अन्य चीजों के पैटर्न मिलान के बीच (गोले जैसे शेल bash, dashउबंटू का डिफ़ॉल्ट /bin/sh, और kshइस मानक का पालन करता है)। 2.13.3 अनुभाग से फाइलनाम विस्तार के लिए प्रयुक्त पैटर्न :

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

यह निश्चित रूप से एक साइड इफेक्ट है - मिलान नाम है कि शाब्दिक रूप से हो सकता है *.txt। में nullglobविकल्प bashऔर zshमदद कर सकता है: यदि वह विकल्प के माध्यम से सक्षम किया गया है shopt -s nullglob(और यह डिफ़ॉल्ट रूप से सक्षम नहीं है जो इस प्रश्न पर लागू होता है), तो ग्लोबस्टार को खाली स्ट्रिंग में विस्तारित किया जाएगा जब कोई मिलान फ़ाइल नाम नहीं मिला। ksh93इसका अपना उन्नत पैटर्न मिलान तंत्र है जो समान प्रभाव को प्राप्त करता है~(N)*.txt

यह भी देखें कि नलग्लोब डिफ़ॉल्ट क्यों नहीं है?

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.