कुछ आदेशों के साथ BASH प्रक्रिया प्रतिस्थापन कार्य क्यों नहीं करता है?


29

मौके पर प्रक्रिया प्रतिस्थापन उम्मीद के मुताबिक काम नहीं करेगा। यहाँ एक उदाहरण है:

इनपुट:

gcc <(echo 'int main(){return 0;}')

आउटपुट:

/dev/fd/63: file not recognized: Illegal seek
collect2: error: ld returned 1 exit status

इनपुट:

लेकिन जब यह एक अलग कमांड के साथ प्रयोग किया जाता है, तो यह अपेक्षित है:

grep main <(echo 'int main(){return 0;}')

आउटपुट:

int main(){return 0;}

मैंने अन्य आदेशों के साथ समान विफलताओं पर ध्यान दिया है (यानी प्रक्रिया प्रतिस्थापन से फ़ाइल की अपेक्षा करने वाला कमांड उपयोग /dev/fd/63या समान नहीं कर सकता है )। इस विफलता के साथ gccअभी हाल ही में है। क्या कुछ सामान्य नियम हैं जो मुझे यह निर्धारित करने के लिए पता होना चाहिए कि प्रक्रिया प्रतिस्थापन इस तरह से विफल हो जाएगा और इसका उपयोग नहीं किया जाना चाहिए?

मैं Ubuntu 12.04 पर इस BASH संस्करण का उपयोग कर रहा हूं (मैंने इसे आर्क और डेबियन में भी देखा है):
GNU बैश, संस्करण 4.3.11 (1) -release (i686-pc-linux-gnu)


1
illegal seekउत्तर की तरह दिखता है - जो |pipeकि bashनिष्पादित कार्यक्रम को इंगित करता है वह एक खोजने योग्य फ़ाइल नहीं है। शायद अगर आप echo data | command /dev/fd/0एक कार्यक्रम में सफलतापूर्वक नहीं कर सकते हैं तो आपके पास समान भाग्य w / होगा <(cmd)। यह ऑन-डिस्क फ़ाइल प्रदान नहीं करता है - यह सिर्फ एक तर्क को प्रतिस्थापित करता है जो एक पाइप फ़ाइल डिस्क्रिप्टर की ओर इशारा करता है।
माइकस

2
इस विशेष मामले में, हालांकि जीसीसी मानक इनपुट को स्वीकार कर सकता है , यह (डिफ़ॉल्ट रूप से) भाषा का निर्धारण करने के लिए फ़ाइल नाम एक्सटेंशन का उपयोग करता है। तो कोशिश करो gcc -xc <(echo 'int main(){return 0;}')(जो Cस्पष्ट रूप से भाषा सेट करता है )।
स्टीलड्राइव

मुझे यहाँ अपने स्वयं के प्रश्न के उत्तर में निर्देशित किया गया था, जो कि इसका एक और उदाहरण है। superuser.com/questions/1243405 । इस प्रश्न को बेहतर बनाने के लिए धन्यवाद कि मैं कितना सक्षम था।
जोनाथन हार्टले

जवाबों:


33

एक विशेष फ़ाइल में प्रक्रिया प्रतिस्थापन परिणाम (जैसे /dev/fd/63आपके उदाहरण में) एक नामित पाइप के पढ़ने के अंत की तरह व्यवहार करता है। यह फ़ाइल खोली और पढ़ी जा सकती है, लेकिन लिखी नहीं गई, खोजी नहीं गई।

कमांड जो अपने तर्कों को शुद्ध धाराओं के रूप में मानते हैं, जबकि कमांड उन फाइलों में तलाश करने की अपेक्षा करते हैं जो उन्हें दिए गए हैं (या उन्हें लिखें) काम नहीं करेंगे। आदेश की तरह इच्छा काम क्या आम तौर पर एक फिल्टर माना जाता है कि: cat, grep, sed, gzip, awk, आदि ... एक आदेश है कि होगा काम नहीं की तरह एक संपादक है का एक उदाहरण viया की तरह एक फ़ाइल आपरेशन mv

gccअपनी इनपुट फ़ाइलों पर यादृच्छिक अभिगम करने में सक्षम होना चाहता है ताकि वे यह पता लगा सकें कि वे किस भाषा में लिखे गए हैं। यदि आप इसके बजाय gccइनपुट फ़ाइल की भाषा के बारे में संकेत देते हैं, तो फ़ाइल को स्ट्रीम करने में खुशी होती है:

gcc -x c <(echo 'int main(){return 0;}')

प्रक्रिया प्रतिस्थापन के बिना सरल और अधिक सरल रूप भी काम करता है:

echo 'int main(){return 0;}' | gcc -x c -

ध्यान दें कि यह विशिष्ट नहीं है bash। प्रक्रिया के प्रतिस्थापन का समर्थन करने वाले सभी गोले उसी तरह व्यवहार करते हैं।


Gcc वर्कअराउंड के लिए +1 लेकिन मैं फाइलों से संबंधित आपकी बात के बारे में निश्चित नहीं हूं। <()प्रारूप सभी इरादों और उद्देश्यों के लिए एक फ़ाइल की तरह कार्य करना चाहिए। वास्तव में, मैं ऐसी किसी भी कमांड के बारे में नहीं जानता, जो ऐसी फाइल की उम्मीद करती हो, जो इससे खुश नहीं होगी <()। जो काम नहीं करते हैं वे फाइल नाम की अपेक्षा करते हैं , फाइलें नहीं। उदाहरण के लिए, grep -fकिसी फ़ाइल की अपेक्षा करता है और उसके साथ ठीक काम करता है <()
terdon

4
@terndon निश्चित रूप से <()एक फ़ाइल नाम का निर्माण करता है (निर्माण /proc/self/fd/somethingमेरे सिस्टम पर फैलता है)। यह नाम, जब खोला जाता है, S_IFIFOतो एक नियमित रूप से फ़ाइल ( S_IFREG) के बजाय एक नामित पाइप ( ) के रीड एंड की तरह कार्य करता है जो समर्थन करता है read()और अन्य नहीं है seek()
Celada

7
ध्यान दें कि zshविशेष रूप से उस उद्देश्य के लिए अस्थायी फ़ाइलों का उपयोग करने वाले प्रक्रिया प्रतिस्थापन के 3 प्रकार का समर्थन करता है:gcc =(echo 'int main(){return 0;}')
स्टीफन चेज़लस

शायद संबंधित है , लेकिन साथ काम करता है <(echo '...')लेकिन साथ नहीं <(git show ...)। किसी भी विचार क्यों हो सकता है?
जर्नी हीस

2
जीसीसी "अपनी इनपुट फ़ाइलों पर यादृच्छिक अभिगम नहीं करता है ताकि यह पता लगाया जा सके कि वे किस भाषा में लिखे गए हैं।" यह सिर्फ फ़ाइल नाम के विस्तार को देखता है। यदि फ़ाइल नाम में कोई एक्सटेंशन नहीं है (या यदि इसकी कोई पहचान नहीं है), तो GCC मानती है कि फ़ाइल एक ऑब्जेक्ट फ़ाइल या लिंकर स्क्रिप्ट है और इसे पास करती है ld(जो ऑब्जेक्ट फॉर्मेट का पता लगाती है)। -xएक संकेत नहीं है; यह एक घोषणा है। यदि आप निर्दिष्ट करते हैं -x f95, तो जीसीसी अपने नाम या सामग्री की परवाह किए बिना फ़ाइल को फोरट्रान -95 संकलक को पास कर देगा। Gcc.gnu.org/onbuildocs/gcc-8.1.0/gcc/Overall-Options.html
rici
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.