इसलिए मैं एक जवाब देना चाहता था जैसे कि लोमना का, लेकिन मुझे लगता है कि मेरा शायद थोड़ा सरल और थोड़ा अधिक लाभकारी शुद्ध-बॉर्न-शेल समाधान है:
# You want to pipe command1 through command2:
exec 4>&1
exitstatus=`{ { command1; printf $? 1>&3; } | command2 1>&4; } 3>&1`
# $exitstatus now has command1's exit status.
मुझे लगता है कि यह अंदर से बाहर से सबसे अच्छी तरह से समझाया गया है - कमांड 1 अपने नियमित आउटपुट को प्रिंटआउट (फाइल डिस्क्रिप्टर 1) पर निष्पादित करेगा और प्रिंट करेगा, फिर एक बार यह पूरा हो जाने पर, प्रिंटफ़ निष्पादित करेगा और icdand1 के एक्जिट कोड को अपने स्टडआउट पर प्रिंट करेगा, लेकिन उस स्टडआउट को पुनर्निर्देशित किया जाएगा। फ़ाइल विवरणक 3।
जबकि कमांड 1 चल रहा है, इसके स्टडआउट को कमांड 2 पर प्रिंट किया जा रहा है (प्रिंटफ का आउटपुट कभी भी कमांड 2 पर नहीं जाता है क्योंकि हम इसे 1 के बजाय फाइल डिस्क्रिप्टर 3 में भेजते हैं, जो कि पाइप पढ़ता है)। फिर हम डिस्क्रिप्टर 4 को फाइल करने के लिए कमांड 2 के आउटपुट को रीडायरेक्ट करते हैं, ताकि वह फाइल डिस्क्रिप्टर 1 से भी बाहर रहे - क्योंकि हम फाइल डिस्क्रिप्टर 1 को थोड़े समय बाद के लिए फ्री चाहते हैं, क्योंकि हम फाइल डिस्क्रिप्टर 3 पर प्रिंटफ आउटपुट को फाइल डिस्क्रिप्टर में वापस लाएँगे। 1 - क्योंकि यह वही है जो कमांड सबस्टेशन (बैकटिक्स) पर कब्जा कर लेगा और इसे वैरिएबल में रखा जाएगा।
जादू का अंतिम बिट यह है कि पहले exec 4>&1
हमने एक अलग कमांड के रूप में किया था - यह बाहरी शेल के स्टॉटआउट की एक कॉपी के रूप में फाइल डिस्क्रिप्टर 4 को खोलता है। कमांड प्रतिस्थापन अपने अंदर के कमांड के परिप्रेक्ष्य से मानक आउट पर जो कुछ भी लिखा गया है, उस पर कब्जा कर लेगा - लेकिन चूंकि कमांड प्रतिस्थापन के संबंध में कमांड 2 का आउटपुट डिस्क्रिप्टर 4 को फाइल करने जा रहा है, कमांड प्रतिस्थापन इसे कैप्चर नहीं करता है - हालांकि एक बार यह कमांड प्रतिस्थापन के "आउट" हो जाता है यह प्रभावी रूप से अभी भी स्क्रिप्ट की समग्र फ़ाइल डिस्क्रिप्टर 1 पर जा रहा है।
( exec 4>&1
एक अलग कमांड होना चाहिए क्योंकि कमांड प्रतिस्थापन के अंदर फ़ाइल डिस्क्रिप्टर पर लिखने की कोशिश करने पर कई सामान्य गोले इसे पसंद नहीं करते हैं, जो कि "बाहरी" कमांड में खोला जाता है जो प्रतिस्थापन का उपयोग कर रहा है। यह करने के लिए सबसे आसान पोर्टेबल तरीका है।)
आप इसे कम तकनीकी और अधिक चंचल तरीके से देख सकते हैं, जैसे कि कमांड के आउटपुट एक-दूसरे को लीपफ्रॉग कर रहे हैं: कमांड 1 से कमांड 2 पाइप, फिर प्रिंटफ का आउटपुट कमांड 2 पर कूदता है ताकि कमांड 2 इसे पकड़ न सके, और फिर कमांड 2 का आउटपुट कमांड प्रतिस्थापन के ऊपर और बाहर प्रिंटफ लैंड के रूप में समय के साथ-साथ प्रतिस्थापन द्वारा कब्जा कर लिया जाता है ताकि यह चर में समाप्त हो जाए, और कमांड 2 का उत्पादन मानक तरीके से लिखे जाने के रूप में मानक तरीके से लिखा जा रहा है एक सामान्य पाइप में।
इसके अलावा, जैसा कि मैं समझता हूं, $?
अभी भी पाइप में दूसरी कमांड का रिटर्न कोड होगा, क्योंकि चर असाइनमेंट, कमांड सबस्टेशन और कम्पाउंड कमांड सभी प्रभावी रूप से उनके अंदर कमांड के रिटर्न कोड के लिए पारदर्शी हैं, इसलिए रिटर्न की स्थिति कमांड 2 को बाहर प्रचारित किया जाना चाहिए - यह, और एक अतिरिक्त फ़ंक्शन को परिभाषित नहीं करना है, यही कारण है कि मुझे लगता है कि यह lesmana द्वारा प्रस्तावित एक की तुलना में कुछ बेहतर समाधान हो सकता है।
कैविट्स लेमनमा का उल्लेख है, यह संभव है कि कमांड 1 कुछ बिंदुओं पर फ़ाइल डिस्क्रिप्टर 3 या 4 का उपयोग करके समाप्त होगा, इसलिए अधिक मजबूत होने के लिए, आप ऐसा करेंगे:
exec 4>&1
exitstatus=`{ { command1 3>&-; printf $? 1>&3; } 4>&- | command2 1>&4; } 3>&1`
exec 4>&-
ध्यान दें कि मैं अपने उदाहरण में यौगिक आदेशों का उपयोग करता हूं, लेकिन उपधाराएं ( ( )
इसके बजाय का उपयोग { }
करना भी काम करेगा, हालांकि संभवतः कम कुशल हो सकता है।)
फ़ाइल डिस्क्रिप्टर को इनहेरिट करने वाली प्रक्रिया से इनहेरिट करता है, इसलिए संपूर्ण दूसरी पंक्ति फ़ाइल डिस्क्रिप्टर चार को इनहेरिट करेगी, और उसके बाद कंपाउंड कमांड 3>&1
फ़ाइल डिस्क्रिप्टर तीन को इनहेरिट करेगी। इसलिए यह 4>&-
सुनिश्चित करता है कि आंतरिक कंपाउंड कमांड फ़ाइल डिस्क्रिप्टर चार 3>&-
को इनहेरिट नहीं करेगा , और वॉयल डिस्क्रिप्टर तीन को इनहेरिट नहीं करेगा, इसलिए कमांड 1 को एक 'क्लीनर', अधिक मानक वातावरण मिलता है। तुम भी भीतरी चल सकता 4>&-
करने के लिए अगले 3>&-
है, लेकिन मैं आंकड़ा क्यों नहीं बस तक संभव हो, इसके दायरे की सीमा।
मुझे यकीन नहीं है कि चीजें कितनी बार फ़ाइल डिस्क्रिप्टर तीन और चार का सीधे उपयोग करती हैं - मुझे लगता है कि ज्यादातर समय प्रोग्राम ऐसे सिस्कल्स का उपयोग करते हैं जो नॉट-ऑन-ऑफ-द-क्षण फ़ाइल डिस्क्रिप्टर लौटाते हैं, लेकिन कभी-कभी कोड डिस्क्रिप्टर 3 को सीधे फाइल करने के लिए लिखते हैं, मैं लगता है (मैं एक प्रोग्राम को देखने के लिए फ़ाइल डिस्क्रिप्टर की जाँच कर सकता हूं कि क्या यह खुला है, और इसका उपयोग कर रहा है या नहीं तो इसके अनुसार अलग-अलग व्यवहार कर रहा है)। इसलिए उत्तरार्द्ध संभवतः सामान्य प्रयोजन के मामलों को ध्यान में रखने और उपयोग करने के लिए सबसे अच्छा है।