'Ls' और 'इको $ (ls)' के बीच अंतर


27

दो शेल नमूनों पर विचार करें

$ ls
myDoc.html
SomeDirectory
someDoc.txt

तथा

$ echo $(ls)
myDoc.html SomeDirectory someDoc.txt

पहला निष्पादित करता है ls, जैसा कि मैं समझता हूं, वर्तमान कार्यशील निर्देशिका की सामग्री को stdoutफ़ाइल में जोड़ता है (जो कि टर्मिनल प्रदर्शित करता है)। क्या ये सही है?

दूसरा lsकमांड का मूल्य लेता है (जिसका अर्थ है कि वर्तमान कार्यशील निर्देशिका की सामग्री है) और इसे stdoutफ़ाइल में प्रिंट करता है । क्या ये सही है?

दो कमांड अलग-अलग आउटपुट क्यों देते हैं?


1
क्योंकि तुम प्रतिध्वनि कर रहे हो। इको कमांड के इनपुट के रूप में ls का आउटपुट।
एकिडेमोन

यह "अपेक्षित" व्यवहार है, जिसे कोई शीघ्र ही समझा देगा। हालाँकि, क्या आप सुनिश्चित हैं कि आपके lsद्वारा प्रति पंक्ति आपको कई आइटम नहीं दिए गए हैं?
रोइमा

@roaima स्तंभित ls एक bsd "सुविधा" का अवशेष है। यूनिक्स संस्करण प्रति पंक्ति एक प्रविष्टि प्रिंट करते हैं
स्टीव कॉक्स

@SteveCox मैंने शुरुआती एसवीआर 4 के बाद से उचित यूनिक्स का उपयोग नहीं किया है इसलिए मेरी मेमोरी थोड़ी धुंधली है। याद दिलाने के लिए शुक्रिया।
रोज़ा

क्यों नहीं echo *?
jdh8

जवाबों:


70

जब आप यह आदेश चलाते हैं:

ls

टर्मिनल का आउटपुट प्रदर्शित करता है ls

जब आप यह आदेश चलाते हैं:

echo $(ls)

शेल इसके आउटपुट को कैप्चर $(ls)करता है और इस पर शब्द विभाजन करता है। डिफॉल्ट के साथ IFS, इसका मतलब है कि न्यूलाइन वर्णों सहित सफेद स्थान के सभी अनुक्रमों को एक रिक्त स्थान से बदल दिया जाता है। यही कारण है कि आउटपुट echo $(ls)एक पंक्ति में दिखाई देता है।

शब्द विभाजन की एक उन्नत चर्चा के लिए, ग्रेग के अक्सर पूछे जाने वाले प्रश्न देखें ।

दमन शब्द का विभाजन

शेल उद्धरणों में तार पर शब्द विभाजन नहीं करता है। इस प्रकार, आप शब्द विभाजन को दबा सकते हैं और बहु-उत्पादन को बनाए रख सकते हैं:

echo "$(ls)"

ls और बहुस्तरीय उत्पादन

आपने देखा होगा कि lsकभी-कभी प्रति पंक्ति एक से अधिक फ़ाइल प्रिंट होती हैं:

$ ls
file1  file2  file3  file4  file5  file6

यह तब होता है जब lsकिसी टर्मिनल में आउटपुट जाता है। जब आउटपुट सीधे टर्मिनल पर नहीं जा रहा है, तो lsइसकी डिफ़ॉल्ट प्रति लाइन एक फाइल में बदल जाती है:

$ echo "$(ls)"
file1
file2
file3
file4
file5
file6

इस व्यवहार में प्रलेखित है man ls

एक और सूक्ष्मता: आदेश प्रतिस्थापन और अनुगामी newlines

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

$ echo "$(printf "\n")"

$ echo "$(printf "\n\n\n\n\n")"

$ 

इस व्यवहार में प्रलेखित है man bash

एक और आश्चर्य: pathname विस्तार, दो बार

चलो तीन फाइलें बनाते हैं:

$ touch 'file?' file1 file2

ls file?और बीच के अंतर को देखें echo $(ls file?):

$ ls file?
file?  file1  file2
$ echo $(ls file?)
file? file1 file2 file1 file2

के मामले में echo $(ls file?), फ़ाइल ग्लोब file?को दो बार विस्तारित किया जाता है , जिससे फ़ाइल नाम file1और file2आउटपुट में दो बार दिखाई देते हैं। इसका कारण यह है, जैसा कि जेफिकिन्स बताते हैं, pathname का विस्तार पहले शेल द्वारा किया जाता है, पहले lsचलाया जाता है और फिर फिर से echoचलने से पहले ।

यदि हम दोहरे उद्धरण चिह्नों का उपयोग करते हैं तो दूसरा पाथनेम विस्तार को दबाया जा सकता है:

$ echo "$(ls file?)"
file?
file1
file2

4
इसके अलावा, isattyअगर आप स्टडआउट ट्टी है, तो आप यह जांच कर सकते हैं कि एलएस इसका उपयोग यह निर्धारित करने के लिए करता है कि रंगों का उपयोग करना है या नहीं।
जानूस ट्रॉल्सन

1
क्या अंतिम कोड स्निपेट में बेमेल नहीं हैं? या $( )वास्तव में एक सिंटैक्स बाधा प्रदान करते हैं ताकि आपको प्रक्षेप करने की आवश्यकता न हो?
बिल्ली

6
@cat $()एक सिंटैक्स अवरोध प्रदान करता है।
रैंडम 832

2
एक और महत्वपूर्ण अंतर: यदि किसी फ़ाइल नाम में वाइल्डकार्ड वर्ण है, तो echoकमांड वाइल्डकार्ड का विस्तार करेगा । उदाहरण के लिए, यदि lsरिटर्न फाइल करता है? file1 file2 , फिर फाइलecho $(ls) लौटेगी ? file1 file2 file1 file2
जेफिकिन्स

1
@ जेफीकीन्स echoवाइल्डकार्ड का विस्तार नहीं करता है; शेल परिणामी विस्तार को तर्क के रूप में पारित करने से पहले करता है echo
चेपनर

0

ls पता है कि यह एक टर्मिनल के लिए उत्पादन भेज रहा है या नहीं।

lsकमांड प्रॉम्प्ट पर निष्पादित करने के लिए आपके छद्म ट्टी को लिखा जाएगा। lsआमतौर पर वसीयत के आउटपुट को रीडायरेक्ट करने से छद्म टट्टी नहीं जाएगी, और lsआउटपुट को अलग तरीके से प्रारूपित करेगी।

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