संपादित करें: मैं देख रहा हूँ कि मैं पटरी से उतर गया और एक अलग सवाल का जवाब देने से समाप्त हो गया। असली सवाल का जवाब पॉल टॉम्बलिन के जवाब में सबसे नीचे है। (यदि आप किसी कारण के लिए अलग-अलग stdout और stderr को पुनर्निर्देशित करने के लिए उस समाधान को बढ़ाना चाहते हैं, तो आप मेरे द्वारा बताई गई तकनीक का उपयोग कर सकते हैं।)
मैं एक जवाब चाह रहा हूँ जो stdout और stderr के बीच अंतर को बरकरार रखता है। दुर्भाग्य से अब तक दिए गए सभी उत्तर जो यह बताते हैं कि भेद जाति-प्रवण हैं: वे अधूरे इनपुट को देखते हुए कार्यक्रमों को जोखिम में डालते हैं, जैसा कि मैंने टिप्पणियों में बताया है।
मुझे लगता है कि मुझे अंत में एक उत्तर मिला है जो भेद को संरक्षित करता है, दौड़ प्रवण नहीं है, और बहुत बुरी तरह से भी नहीं है।
पहला बिल्डिंग ब्लॉक: स्टैडआउट और स्टैडर को स्वैप करने के लिए:
my_command 3>&1 1>&2 2>&3-
दूसरा बिल्डिंग ब्लॉक: यदि हम केवल stderr को फ़िल्टर करना चाहते हैं (जैसे टी), तो हम इसे पूरा कर सकते हैं कि stdout और stderr, फ़िल्टरिंग और फिर स्वैपिंग करके:
{ my_command 3>&1 1>&2 2>&3- | stderr_filter;} 3>&1 1>&2 2>&3-
अब बाकी आसान है: हम शुरुआत में या तो एक स्टडआउट फ़िल्टर जोड़ सकते हैं:
{ { my_command | stdout_filter;} 3>&1 1>&2 2>&3- | stderr_filter;} 3>&1 1>&2 2>&3-
या अंत में:
{ my_command 3>&1 1>&2 2>&3- | stderr_filter;} 3>&1 1>&2 2>&3- | stdout_filter
अपने आप को यह समझाने के लिए कि उपरोक्त दोनों कमांड काम करते हैं, मैंने निम्नलिखित का उपयोग किया:
alias my_command='{ echo "to stdout"; echo "to stderr" >&2;}'
alias stdout_filter='{ sleep 1; sed -u "s/^/teed stdout: /" | tee stdout.txt;}'
alias stderr_filter='{ sleep 2; sed -u "s/^/teed stderr: /" | tee stderr.txt;}'
आउटपुट है:
...(1 second pause)...
teed stdout: to stdout
...(another 1 second pause)...
teed stderr: to stderr
और मेरा संकेत " teed stderr: to stderr
" के तुरंत बाद वापस आता है , जैसा कि अपेक्षित था।
पाद के बारे में zsh :
उपरोक्त समाधान बाश में काम करता है (और शायद कुछ अन्य गोले, मुझे यकीन नहीं है), लेकिन यह zsh में काम नहीं करता है। दो कारण हैं कि यह zsh में विफल रहता है:
- वाक्य-विन्यास
2>&3-
को zsh द्वारा नहीं समझा जाता है; इसे फिर से लिखना होगा2>&3 3>&-
- zsh में (अन्य गोले के विपरीत), यदि आप किसी फ़ाइल डिस्क्रिप्टर को पहले से ही खोल चुके हैं, तो कुछ मामलों में (मुझे पूरी तरह से समझ में नहीं आता कि यह कैसे तय होता है) इसके बजाय एक अंतर्निहित टी-लाइक व्यवहार करता है। इससे बचने के लिए, आपको इसे रीडायरेक्ट करने से पहले प्रत्येक fd को बंद करना होगा।
इसलिए, उदाहरण के लिए, मेरे दूसरे समाधान को zsh के रूप में फिर से लिखना होगा {my_command 3>&1 1>&- 1>&2 2>&- 2>&3 3>&- | stderr_filter;} 3>&1 1>&- 1>&2 2>&- 2>&3 3>&- | stdout_filter
(जो कि बहुत काम करता है, लेकिन भयानक रूप से क्रिया है )।
दूसरी ओर, आप zsh के लिए बहुत छोटा समाधान पाने के लिए zsh के रहस्यमय अंतर्निहित अंतर्निहित टीज़िंग का लाभ उठा सकते हैं, जो टी को बिल्कुल भी नहीं चलाता है:
my_command >&1 >stdout.txt 2>&2 2>stderr.txt
(मुझे लगता है कि मुझे पता चला है कि डॉक्स से अनुमान नहीं लगाया गया है >&1
और 2>&2
वह चीज है जो zsh की अंतर्निहित टीज़िंग को ट्रिगर करती है; मैंने पाया कि ट्रायल-एंड-एरर के द्वारा।)