वास्तव में क्या है <() in bash (और =) (zsh में)?


36

मैं बैश को लेकर काफी कंफर्टेबल हूं, लेकिन हाल ही में मैं एक ऐसे प्रतिस्थापन में समाप्त हो गया जिसे मैं नहीं जानता था।

वास्तव में क्या है <(<command>)? यह =(<command>)zsh में कैसे तुलना करता है ?

मैं समझता हूं कि यह डिफॉल्ट फाइल डिस्क्रिप्टर के साथ कुछ करना है। मेरे कंप्यूटर में

echo <()

रिटर्न /proc/self/fd/11, जो मुझे स्क्रिप्ट STDOUT की एक प्रति के रूप में मिला, लेकिन यह अभी भी मुझे बहुत भ्रमित लगता है।

जवाबों:


51

इसे प्रक्रिया प्रतिस्थापन कहते हैं।

<(list)वाक्य रचना दोनों के द्वारा समर्थित है, bashऔर zsh। यह एक कमांड ( list) को किसी अन्य कमांड के आउटपुट को पास करने का एक तरीका प्रदान करता है जब पाइप ( |) का उपयोग करना संभव नहीं है। उदाहरण के लिए जब कोई कमांड सिर्फ इनपुट का समर्थन नहीं करता है STDINया आपको कई कमांड के आउटपुट की आवश्यकता होती है:

diff <(ls dirA) <(ls dirB)

<(list)सिस्टम द्वारा समर्थित listहोने पर /dev/fd, एक फ़ाइल के साथ आउटपुट को जोड़ता है, अन्यथा एक नामित पाइप (FIFO) का उपयोग किया जाता है (जो सिस्टम द्वारा समर्थन पर भी निर्भर करता है; न ही मैनुअल का कहना है कि यदि दोनों तंत्र समर्थित नहीं हैं, तो संभवतः यह गर्भपात करता है एक त्रुटि)। फ़ाइल का नाम तब कमांड लाइन पर तर्क के रूप में पारित किया जाता है।


zshइसके अतिरिक्त =(list)संभव प्रतिस्थापन के रूप में समर्थन करता है <(list)=(list)अस्थायी फ़ाइल के साथ फ़ाइल के बजाय /dev/fdया FIFO में उपयोग किया जाता है । <(list)यदि प्रोग्राम को आउटपुट में लेसेक करने की आवश्यकता है , तो इसे प्रतिस्थापन के रूप में उपयोग किया जा सकता है ।

ZSH मैनुअल के अनुसार अन्य मुद्दों के साथ भी हो सकता है कि कैसे <(list)काम करता है:

=के रूप में दोनों रूप से उपयोगी है /dev/fdऔर के नाम पर रखा गया पाइप कार्यान्वयन <(...)कमियां हैं। पूर्व के मामले में, कुछ प्रोग्राम कमांड लाइन पर फ़ाइल की जांच करने से पहले प्रश्न में फ़ाइल डिस्क्रिप्टर को स्वचालित रूप से बंद कर सकते हैं, खासकर अगर यह सुरक्षा कारणों से आवश्यक है जैसे कि प्रोग्राम चल रहा है। दूसरे मामले में, यदि प्रोग्राम वास्तव में फ़ाइल नहीं खोलता है, तो उपधारा पाइप से पढ़ने या लिखने का प्रयास करेगा (एक विशिष्ट कार्यान्वयन में, अलग-अलग ऑपरेटिंग सिस्टम में अलग-अलग व्यवहार हो सकते हैं) हमेशा के लिए ब्लॉक हो जाते हैं और स्पष्ट रूप से मारे जाते हैं। । दोनों ही मामलों में, शेल वास्तव में एक पाइप का उपयोग करके जानकारी की आपूर्ति करता है, ताकि प्रोग्राम जो lseek(2)फ़ाइल पर लेसेक (मैन पेज देखें ) की अपेक्षा करता है, वह काम नहीं करेगा।


इससे मुझे यह पता लगाने में मदद मिली कि मैकओएस pfctl -f <(echo "pf rules")खराब फाइल डिस्क्रिप्टर क्यों कहेगा। इसके बजाय zsh और = (इको "pf रूल्स" का उपयोग करके) काम करता है।
जॉनी

9

ध्यान दें, यह एक बाश उत्तर है, न कि zsh।

ऐसे मामले हैं जहां आप पाइप का उपयोग नहीं कर सकते हैं:

some_command | some_other_command

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

cat file | while read line; do ((count++)); done
echo $count

एक रिक्त रेखा प्रदर्शित करेगा, क्योंकि $countवर्तमान शेल में चर मौजूद नहीं है।

एक बैश प्रक्रिया प्रतिस्थापन आपको "कुछ_कमांड" आउटपुट से पढ़ने की अनुमति देकर इस पहेली से बचने की अनुमति देता है जैसे आप एक फ़ाइल से

while read line; do ((count++)); done < <(cat file)
# ....................................1.2
echo $count   # the variable *does* exist in the current shell

(1) एक सामान्य इनपुट पुनर्निर्देशन है। (2) <()प्रक्रिया प्रतिस्थापन सिंटैक्स की शुरुआत है ।


2
= (cmdlist) zsh में लगभग समान प्रभाव (<cmdlist) bash में है, लेकिन यह पुनर्निर्देशन के लिए cmdlist के आउटपुट के साथ एक अस्थायी फ़ाइल बनाता है (और तैयार होने पर हटाता है)। यह अच्छा है जब मांग कार्यक्रम में संभावित रूप से किया जाता है। <(cmdlist) को zsh द्वारा भी जाना जाता है।
गोमबाई संडोर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.