बिल्ली का बेकार उपयोग?


101

यह संभवतः कई FAQ में है - उपयोग करने के बजाय:

cat file | command

(जिसे बिल्ली का बेकार उपयोग कहा जाता है), सही तरीका माना जाता है:

command < file

2 में, "सही" तरीका - ओएस को एक अतिरिक्त प्रक्रिया को स्पॉन करने की आवश्यकता नहीं है।
यह जानने के बावजूद, मैंने 2 कारणों से बेकार बिल्ली का उपयोग करना जारी रखा।

  1. अधिक सौंदर्यवादी - मुझे पसंद है जब डेटा केवल बाएं से दाएं समान रूप से चलता है। और यह आसान को बदलने के लिए catकुछ और के साथ ( gzcat, echo, ...), एक 2 फ़ाइल जोड़ने या नई फिल्टर डालने ( pv, mbuffer, grep...)।

  2. मैंने "महसूस किया" कि यह कुछ मामलों में तेज़ हो सकता है। तेज़ क्योंकि 2 प्रक्रियाएँ हैं, पहला ( cat) पठन करता है और दूसरा जो कुछ भी करता है। और वे समानांतर में चल सकते हैं, जिसका अर्थ है कभी-कभी तेजी से निष्पादन।

क्या मेरा तर्क सही है (2 कारण के लिए)?


22
catएक पहचान पाइप है । यह केवल इसके इनपुट को इसके आउटपुट में स्ट्रीम करता है। श्रृंखला में दूसरा कार्यक्रम वही तर्क आप के पास से अपने इनपुट ले जा सकते हैं तो cat(या मानक इनपुट से, अगर आप कोई तर्क पारित), तो catहै बिल्कुल बेकार है और केवल एक अतिरिक्त प्रक्रिया काँटेदार की जा रही है और एक अतिरिक्त पाइप से किया जा रहा में परिणाम बनाया था।
Frédéric Hamidi

11
@ Frédéric Hamidi जब बिल्ली के पास कोई तर्क नहीं है या इसका तर्क नहीं है -, यह एक पहचान पाइप है। जब इसके पास एक से अधिक गैर-डैश फ़ाइल नाम तर्क होता है, तो यह एक पहचान पाइप से कुछ अधिक हो जाता है, हालांकि, और एक वास्तविक उद्देश्य की सेवा शुरू करता है।
कोजिरो

3
Partmaps.org के लिए पूर्व में लोकप्रिय लिंक दुर्भाग्य से मृत है। सामग्री अब porkmail.org/era/unix/award.html
tripleee


2
मैं देखता हूं कि यदि आप सही डेटाफ़्लो (कारण 1) दिखाना चाहते हैं, तो आप फ़ाइल को पुनर्निर्देशन को कमांड से पहले डालकर ऐसा कर सकते हैं, जैसे <file command1 | command2कि सौंदर्यशास्त्र के बारे में असहमति होगी।
होल्डनवेब

जवाबों:


81

मुझे आज तक इस पुरस्कार के बारे में पता नहीं था, जब कुछ बदमाशों ने मेरे एक जवाब के लिए मुझ पर UUOC पिन करने की कोशिश की । यह एक था cat file.txt | grep foo | cut ... | cut ...। मैंने उसे अपने दिमाग का एक टुकड़ा दिया और ऐसा करने के बाद ही उसने मुझे इस पुरस्कार की उत्पत्ति और ऐसा करने की प्रथा का जिक्र किया। आगे की खोज ने मुझे इस प्रश्न की ओर अग्रसर किया। सचेत रूप से विचार के बावजूद कुछ दुर्भाग्य से, किसी भी उत्तर में मेरा तर्क शामिल नहीं था।

मुझे उसके जवाब में रक्षात्मक होने का मतलब नहीं था। आखिरकार, मेरे छोटे वर्षों में, मैंने कमांड लिखी होगी grep foo file.txt | cut ... | cut ...क्योंकि जब भी आप बार-बार सिंगल grepएस करते हैं, तो आप फ़ाइल तर्क की नियुक्ति सीखते हैं और यह तैयार ज्ञान है कि पहले पैटर्न है और बाद में फ़ाइल नाम हैं।

इसका उपयोग करने के लिए एक सचेत पसंद था catजब मैंने सवाल का जवाब दिया, आंशिक रूप से "अच्छे स्वाद" (लिनुस टॉर्वाल्ड्स के शब्दों में) के कारण, लेकिन मुख्य रूप से फ़ंक्शन के सम्मोहक कारण के लिए।

उत्तरार्द्ध कारण अधिक महत्वपूर्ण है इसलिए मैं इसे पहले बाहर कर दूंगा। जब मैं एक समाधान के रूप में एक पाइपलाइन की पेशकश करता हूं तो मुझे उम्मीद है कि यह पुन: प्रयोज्य होगा। यह काफी संभावना है कि एक पाइप लाइन के अंत में जोड़ा जाएगा या किसी अन्य पाइपलाइन में लगाया जाएगा। उस स्थिति में एक फ़ाइल तर्क को पुन: प्रयोज्यता पर शिकंजा देने के लिए, और संभवत: फ़ाइल तर्क मौजूद होने पर त्रुटि संदेश के बिना चुपचाप ऐसा करते हैं । अर्थात। grep foo xyz | grep bar xyz | wcआपको कितनी लाइनें xyzमिलेंगी, barजबकि आप उन लाइनों की संख्या की अपेक्षा कर रहे हैं जिनमें दोनों fooऔर हैं bar। त्रुटियों के लिए उपयोग करने से पहले एक पाइपलाइन में एक कमांड के लिए तर्क को बदलना। इसे मौन विफलताओं की संभावना से जोड़ें और यह एक विशेष रूप से कपटी अभ्यास बन जाता है।

पूर्व कारण "बहुत अच्छा स्वाद " के बाद से महत्वहीन नहीं है, केवल ऊपर की मूक विफलताओं जैसी चीजों के लिए एक सहज अवचेतन तर्क है जो आप उस समय सही नहीं सोच सकते हैं जब कोई व्यक्ति शिक्षा की आवश्यकता को कहता है "लेकिन नहीं है" वह बिल्ली बेकार है ”।

हालाँकि, मैं पूर्व के "अच्छे स्वाद" के कारण भी अवगत कराने का प्रयास करूँगा जिसका मैंने उल्लेख किया है। यही कारण है कि यूनिक्स के रूढ़िवादी डिजाइन भावना के साथ करना है। grepकरता है cutऔर नहीं lsकरता है grep। इसलिए बहुत कम से कम grep foo file1 file2 file3डिजाइन की भावना के खिलाफ जाता है। इसे करने का ऑर्थोगोनल तरीका है cat file1 file2 file3 | grep foo। अब, grep foo file1यह केवल एक विशेष मामला है grep foo file1 file2 file3, और यदि आप इसका इलाज नहीं करते हैं तो आप कम से कम ब्रेन क्लॉक चक्र का उपयोग करके बेकार बिल्ली पुरस्कार से बचने की कोशिश कर रहे हैं।

यह हमें उस तर्क की ओर ले जाता है जो grep foo file1 file2 file3समवर्ती है, और catसमवर्ती है, इसलिए यह उचित है, cat file1 file2 file3लेकिन क्योंकि catसमवर्ती नहीं है cat file1 | grep fooइसलिए हम catऔर सर्वशक्तिमान यूनिक्स दोनों की भावना का उल्लंघन कर रहे हैं । खैर, अगर ऐसा होता तो Unix को एक फाइल के आउटपुट को पढ़ने के लिए अलग से कमांड की जरूरत होती और इसे stdout में थूकना (इसे paginate नहीं करना चाहिए या stdout को सिर्फ एक शुद्ध थूक)। तो आपके पास ऐसी स्थिति होगी जहां आप कहते हैं cat file1 file2या आप कहते हैं dog file1और ईमानदारी से याद रखें cat file1कि पुरस्कार प्राप्त करने से बचने के लिए, जबकि dog file1 file2उम्मीद है कि बचने के बाद से dogकई फ़ाइलों को निर्दिष्ट किए जाने पर डिज़ाइन में त्रुटि हो सकती है।

उम्मीद है, इस बिंदु पर, आप यूनिक्स डिजाइनरों के साथ सहानुभूति रखते हैं, जिसमें एक अलग कमांड को शामिल करने के लिए एक फाइल को स्टडआउट करने के लिए नहीं है, जबकि catइसे किसी अन्य नाम देने के बजाय संक्षिप्त नाम देने के लिए भी । <edit>गलत टिप्पणियों को हटा दिया गया <, वास्तव में, <एक फाइल को स्टडआउट करने के लिए एक कुशल नो-कॉपी सुविधा है जिसे आप पाइप लाइन की शुरुआत में रख सकते हैं इसलिए यूनिक्स डिजाइनरों ने इसके लिए विशेष रूप से कुछ शामिल किया</edit>

अगला सवाल यह है कि ऐसे आदेश क्यों महत्वपूर्ण हैं जो केवल एक फाइल थूकते हैं या किसी फाइल को आगे बढ़ाने के लिए बिना किसी प्रोसेसिंग के स्टेपआउट करने के लिए कहते हैं? एक कारण हर एक यूनिक्स कमांड होने से बचने के लिए है जो कम से कम एक कमांड लाइन फ़ाइल तर्क को पार्स करने के लिए मानक इनपुट पर संचालित होता है और मौजूद होने पर इसे इनपुट के रूप में उपयोग करना है। दूसरा कारण उपयोगकर्ताओं को याद रखने से बचना है: (ए) फ़ाइल नाम के तर्क जहां जाते हैं; और (बी) ऊपर वर्णित के रूप में मूक पाइपलाइन बग से बचें।

यही कारण है कि हमारे grepपास अतिरिक्त तर्क क्यों हैं । औचित्य उपयोगकर्ता-प्रवाह के लिए आदेशों के लिए अनुमति देता है जो अक्सर और एक स्टैंड-अलोन आधार पर उपयोग किया जाता है (बजाय एक पाइपलाइन के रूप में)। यह प्रयोज्य में एक महत्वपूर्ण लाभ के लिए रूढ़िवाद का एक मामूली समझौता है। सभी आदेशों को इस तरह से डिज़ाइन नहीं किया जाना चाहिए और जिन आदेशों का अक्सर उपयोग नहीं किया जाता है, उन्हें पूरी तरह से फ़ाइल तर्कों के अतिरिक्त तर्क से बचना चाहिए (याद रखें कि अतिरिक्त तर्क अनावश्यक नाजुकता (बग की संभावना) की ओर जाता है)। अपवाद के मामले में जैसे फ़ाइल तर्क देने की अनुमति है grep। (वैसे, ध्यान दें कि lsस्वीकार न करने के लिए एक पूरी तरह से अलग कारण है, लेकिन बहुत ज्यादा फ़ाइल तर्क की आवश्यकता है)

अंत में, जो बेहतर किया जा सकता था, वह यह है कि अगर इस तरह की असाधारण आज्ञाएँ grep(लेकिन जरूरी नहीं ls) एक त्रुटि उत्पन्न करती हैं यदि फ़ाइल के तर्कों को निर्दिष्ट करते समय मानक इनपुट भी उपलब्ध हो।


53
ध्यान दें कि जब grepकई फ़ाइल नामों के साथ आह्वान किया जाता है, तो यह उस फ़ाइल के नाम के साथ मिली पंक्तियों को उपसर्ग करता है जो इसमें पाया गया था (जब तक कि आप उस व्यवहार को बंद नहीं करते)। यह अलग-अलग फाइलों में लाइन नंबर भी रिपोर्ट कर सकता है। यदि केवल catफीड करने के लिए उपयोग किया जाता है grep, तो आप फ़ाइल नाम खो देते हैं, और लाइन नंबर सभी फाइलों पर निरंतर होते हैं, प्रति फ़ाइल नहीं। इस प्रकार grepकई फ़ाइलें जो स्वयं catनहीं संभाल सकती हैं, उन्हें संभालने के लिए कारण हैं । एकल फ़ाइल और शून्य फ़ाइल मामले सामान्य बहु-फ़ाइल उपयोग के विशेष मामले हैं grep
जोनाथन लेफ़लर

38
के रूप में में बताया गया है इस सवाल का जवाब द्वारा Kojiro , इसके साथ पाइप लाइन शुरू करने के लिए पूरी तरह से संभव है और कानूनी है < file command1 ...। यद्यपि I / O पुनर्निर्देशन ऑपरेटरों के लिए पारंपरिक स्थिति कमांड नाम और उसके तर्कों के बाद है, जो केवल सम्मेलन है और अनिवार्य प्लेसमेंट नहीं है। <फ़ाइल नाम पूर्व में होना करने के लिए है। तो, वहाँ के बीच एक पूर्ण समरूपता >outputऔर <inputपुनर्निर्देशन के करीब है <input command1 -opt 1 | command2 -o | command3 >output:।
जोनाथन लेफ्लर

15
मुझे लगता है कि एक कारण है कि लोग मुख्य रूप से शिक्षित करने के लिए यूयूओसी पत्थर (मेरे सहित) क्यों फेंकते हैं। कभी-कभी लोग गीगाबाइट की विशाल टेक्स्टफाइल्स प्रक्रिया करते हैं जिसमें पाइप (यूयूओसी, न्यूनतम अनुक्रमिक ग्रीप्स को एक, एसो में गिराना) महत्वपूर्ण होता है और अक्सर यह इस सवाल के आधार पर सुरक्षित रूप से माना जा सकता है कि ओपी वास्तव में सिर्फ इतना जानता है कि छोटे ट्वीक हो सकते हैं। विशाल प्रदर्शन प्रभाव। मैं मस्तिष्क चक्रों के बारे में आपकी बात से पूरी तरह सहमत हूं और इसीलिए मैं जरूरत न होने पर भी नियमित रूप से बिल्ली का उपयोग कर पाता हूं। लेकिन यह जानना जरूरी है कि इसकी जरूरत नहीं है।
एड्रियन फ्रुविर्थ

13
कृपया समझे; मैं किसी भी मायने में यह नहीं कह रहा हूं कि catयह बेकार है। ऐसा नहीं है कि catबेकार है; यह है कि एक विशेष निर्माण के उपयोग की आवश्यकता नहीं है cat। यदि आप चाहें, टिप्पणी यह है कि UUoC (के अनुपयोगी उपयोग cat), और नहीं UoUC (अनुपयोगी का उपयोग cat)। ऐसे कई अवसर हैं जब catउपयोग करने के लिए सही उपकरण है; मुझे इसका उपयोग करने में कोई समस्या नहीं है जब यह उपयोग करने के लिए सही उपकरण है (और, वास्तव में, मेरे जवाब में एक मामले का उल्लेख करें)।
जोनाथन लेफ़लर

6
@randomstring मैं आपको सुनता हूं, लेकिन मुझे लगता है कि यह वास्तव में उपयोग के मामले पर निर्भर करता है। जब कमांड लाइन पर इस्तेमाल किया एक अतिरिक्त catपाइप में हो सकता है एक बड़ी बात डेटा पर निर्भर करता है, लेकिन यह इन प्रदर्शन महत्वपूर्ण बातों को लागू करने के बिल्कुल जरूरी हो सकता है जब एक प्रोग्रामिंग वातावरण के रूप में इस्तेमाल नहीं किया जा; विशेष रूप से, bashजिसके साथ काम करते समय , प्रदर्शन-वार, आयताकार आकार के पहिये की तरह होता है ( kshवैसे भी तुलना में । मैं यहां 10x धीमी गति से बात कर रहा हूं - कोई मजाक नहीं)। आप बड़ी लिपियों या विशाल लूप से निपटने के दौरान अपने कांटे (और सिर्फ यही नहीं) का अनुकूलन करना चाहते हैं।
एड्रियन फ्रुविर्थ

58

नहीं!

सबसे पहले, यह कोई फर्क नहीं पड़ता कि एक कमांड में पुनर्निर्देशन कहां होता है। इसलिए यदि आप अपने आदेश के बाईं ओर अपना पुनर्निर्देशन पसंद करते हैं, तो यह ठीक है:

< somefile command

के समान है

command < somefile

दूसरा, जब आप एक पाइप का उपयोग कर रहे हैं तो n + 1 प्रक्रियाएं और एक सबशेल हो रहा है। यह सबसे निश्चित रूप से धीमा है। कुछ मामलों में n शून्य रहा होगा (उदाहरण के लिए, जब आप शेल बिलिन में पुनर्निर्देशित कर रहे हैं), तो उपयोग करके catआप पूरी तरह से अनावश्यक रूप से एक नई प्रक्रिया जोड़ रहे हैं।

एक सामान्यीकरण के रूप में, जब भी आप अपने आप को पाइप का उपयोग करते हुए पाते हैं तो यह देखने में 30 सेकंड लगते हैं कि क्या आप इसे समाप्त कर सकते हैं। (लेकिन शायद 30 सेकंड से अधिक समय लेने के लायक नहीं है।) यहां कुछ उदाहरण दिए गए हैं जहां पाइप और प्रक्रियाओं को अक्सर अनावश्यक रूप से उपयोग किया जाता है:

for word in $(cat somefile);  # for word in $(<somefile); … (or better yet, while read < somefile)

grep something | awk stuff; # awk '/something/ stuff' (similar for sed)

echo something | command; # command <<< something (although echo would be necessary for pure POSIX)

अधिक उदाहरण जोड़ने के लिए स्वतंत्र महसूस करें।


2
खैर, गति वृद्धि ज्यादा नहीं होगी।
डेकरॉन

9
"कमांड" से पहले "<somefile" रखना तकनीकी रूप से आपको दाएं से बाएं देता है, लेकिन यह अस्पष्ट रीडिंग के लिए बनाता है क्योंकि कोई सिंथैटिक सीमांकन नहीं है: < cat grep dogयह दिखाने के लिए एक आकस्मिक उदाहरण है कि आप इनपुट फ़ाइल, कमांड के बीच आसानी से नहीं बता सकते हैं वह इनपुट प्राप्त करता है, और कमांड को तर्क देता है।
नेक्रोमन्ट

2
अंगूठे का नियम मैंने यह तय करने के लिए अपनाया है कि जहां एसटीडीआई पुनर्निर्देशित होता है वह वही करना है जो आश्चर्य के लिए अस्पष्टता / संभावना की उपस्थिति को कम करता है । हठपूर्वक यह कहना कि इससे पहले कि यह नेक्रोमैंसर के मुद्दे को उठाता है, लेकिन हठपूर्वक यह कहे जाने के बाद कि यह वही काम कर सकता है। पर विचार करें: । प्र करता है पर लागू होते हैं , या करने के लिए है जो, द्वारा d ' ? A. यह लागू होता है , लेकिन अस्पष्ट दिखाई दे सकता है। इस मामले में पहले से डालना अधिक स्पष्ट है, यद्यपि कम सामान्य है, और अनुगामी के अनुरूप है । stdout=$(foo bar -exec baz <qux | ENV=VAR quux)<quxfoobaz-execfoofoo<qux fooENV=VAR quux
मार्क जी।

3
@necromancer, <"cat" grep dogवहां पढ़ना आसान है। (मैं आमतौर पर व्हॉट्सएप समर्थक हूं, लेकिन यह विशेष मामला बहुत अपवाद है)।
चार्ल्स डफी

1
@ कोकोजी "यह सबसे निश्चित रूप से धीमा है।" आप यह नहीं लिख सकते हैं कि संख्याओं के समर्थन के बिना। मेरे नंबर यहाँ हैं: oletange.blogspot.com/2013/10/useless-use-of-cat.html (और वे दिखाते हैं कि यह केवल तब धीमा होता है जब आपके पास उच्च ट्रॉटपुट होता है) आप कहाँ हैं?
ओले तांगे

30

मैं अत्यधिक तस्करी वाले यूयूओसी अवार्ड के अधिकांश उदाहरणों से असहमत हूं क्योंकि किसी और को पढ़ाते समय, catकमांड के किसी भी सुविधाजनक या धारक के लिए सुविधाजनक स्थान-धारक होता है जो समस्या या कार्य के लिए उपयुक्त आउटपुट उत्पन्न करता है।

यह विशेष रूप से स्टैक ओवरफ्लो, सर्वरफॉल्ट, यूनिक्स और लिनक्स या एसई साइटों में से किसी भी साइट पर सच है।

यदि कोई विशेष रूप से अनुकूलन के बारे में पूछता है, या यदि आपको ऐसा लगता है कि इसके बारे में अतिरिक्त जानकारी जोड़ना है, तो महान, इस बारे में बात करें कि बिल्ली का उपयोग करना कैसे अक्षम है। लेकिन लोगों को परेशान न करें क्योंकि उन्होंने अपने उदाहरणों में सादगी और सहजता को समझने के बजाय अपने-आप को कैसे-कैसे-कूल-ए-आई के बजाय चुना! जटिलता।

संक्षेप में, क्योंकि बिल्ली हमेशा बिल्ली नहीं होती है।

इसलिए भी क्योंकि ज्यादातर लोग जो UUOCs को देने का आनंद उठाते हैं, वे ऐसा इसलिए करते हैं क्योंकि वे इस बात से अधिक चिंतित होते हैं कि वे लोगों की मदद करने या सिखाने के बारे में कितने 'चतुर' हैं। वास्तव में, वे प्रदर्शित करते हैं कि वे शायद एक और नौसिखिया हैं, जिन्होंने अपने साथियों को हराने के लिए एक छोटी छड़ी पाई है।


अपडेट करें

यहाँ एक और UUOC है जिसे मैंने https://unix.stackexchange.com/a/301194/7696 पर एक उत्तर में पोस्ट किया है :

sqlq() {
  local filter
  filter='cat'

  # very primitive, use getopts for real option handling.
  if [ "$1" == "--delete-blank-lines" ] ; then
    filter='grep -v "^$"'
    shift
  fi

  # each arg is piped into sqlplus as a separate command
  printf "%s\n" "$@" | sqlplus -S sss/eee@sid | $filter
}

यूयूओसी के पेडेंट यह कहेंगे कि यह एक यूयूओसी है क्योंकि $filterखाली स्ट्रिंग को डिफ़ॉल्ट बनाना आसानी से संभव है और ifस्टेटमेंट है filter='| grep -v "^$"'लेकिन आईएमओ, पाइप कैरेक्टर को एम्बेड नहीं करके $filter, यह "बेकार" catइस तथ्य को स्वयं-दस्तावेजीकरण के अत्यंत उपयोगी उद्देश्य को पूरा करता है। कि $filterपर printfलाइन बस एक और तर्क नहीं है के लिए sqlplus, यह एक वैकल्पिक उपयोगकर्ता के चयन उत्पादन फिल्टर है।

यदि एक से अधिक वैकल्पिक उत्पादन फिल्टर करने के लिए किसी भी आवश्यकता है, विकल्प प्रसंस्करण सिर्फ संलग्न कर सकता | whateverकरने के लिए $filterजितनी बार की जरूरत - एक अतिरिक्त catपाइप लाइन में चोट लगी है कुछ भी करने के लिए जा नहीं है या प्रदर्शन के किसी भी ध्यान देने योग्य नुकसान होता है।


11
एक तरफ के रूप में - ==अंदर [ ]POSIX द्वारा निर्दिष्ट नहीं किया गया है, और सभी कार्यान्वयन इसे स्वीकार नहीं करते हैं। मानकीकृत ऑपरेटर बस है =
चार्ल्स डफी

27

UUoC संस्करण के साथ, catफ़ाइल को मेमोरी में पढ़ना है, फिर उसे पाइप पर लिखना है, और कमांड को पाइप से डेटा पढ़ना है, इसलिए कर्नेल को पूरी फ़ाइल को तीन बार कॉपी करना होगा जबकि रीडायरेक्ट मामले में, कर्नेल को केवल एक बार फाइल को कॉपी करना है। तीन बार करने की तुलना में एक बार कुछ करना तेज है।

का उपयोग करते हुए:

cat "$@" | command

एक पूरी तरह से अलग है और जरूरी नहीं कि बेकार का उपयोग हो cat। यह अभी भी बेकार है अगर कमांड एक मानक फ़िल्टर है जो शून्य या अधिक फ़ाइल नाम के तर्क को स्वीकार करता है और बदले में उन्हें संसाधित करता है। trकमांड पर विचार करें : यह एक शुद्ध फिल्टर है जो फ़ाइल नाम के तर्कों को अनदेखा या अस्वीकार करता है। इसके लिए कई फ़ाइलों को खिलाने के लिए, आपको catदिखाए अनुसार उपयोग करना होगा । (बेशक, एक अलग चर्चा है कि इसका डिज़ाइन trबहुत अच्छा नहीं है; ऐसा कोई वास्तविक कारण नहीं है कि इसे एक मानक फ़िल्टर नहीं बनाया जा सकता था।) यह भी मान्य हो सकता है यदि आप चाहते हैं कि कमांड सभी इनपुट को एक के रूप में मानें। एकल फ़ाइल कई अलग-अलग फ़ाइलों के बजाय, भले ही कमांड कई अलग-अलग फ़ाइलों को स्वीकार करेगी: उदाहरण के लिए, wcऐसी एक कमांड है।

यह ऐसा cat single-fileमामला है जो बिना शर्त बेकार है।


26

में रक्षा बिल्ली की:

हाँ,

   < input process > output 

या

   process < input > output 

अधिक कुशल है, लेकिन कई इनवोकेशन में प्रदर्शन के मुद्दे नहीं होते हैं, इसलिए आपको परवाह नहीं है।

एर्गोनोमिक कारण:

हम बाएं से दाएं पढ़ने के लिए उपयोग किए जाते हैं, इसलिए एक कमांड जैसी

    cat infile | process1 | process2 > outfile

समझने के लिए तुच्छ है।

    process1 < infile | process2 > outfile

process1 पर कूदना है, और फिर दाएं से बाएं पढ़ें। इसके द्वारा चंगा किया जा सकता है:

    < infile process1 | process2 > outfile

किसी तरह दिखता है, जैसे कि बाईं ओर इशारा करते हुए एक तीर था, जहां कुछ भी नहीं है। अधिक भ्रामक और लग रहा है जैसे फैंसी उद्धरण है:

    process1 > outfile < infile

और स्क्रिप्ट बनाना अक्सर एक पुनरावृत्ति प्रक्रिया है,

    cat file 
    cat file | process1
    cat file | process1 | process2 
    cat file | process1 | process2 > outfile

जहां आप अपनी प्रगति को कदम-कदम पर देखते हैं, वहीं

    < file 

काम भी नहीं करता। सरल तरीके कम त्रुटि वाले हैं और एर्गोनोमिक कमांड कैटेनेशन बिल्ली के साथ सरल है।

एक अन्य विषय यह है कि कंप्यूटर का उपयोग करने से बहुत पहले और प्रोग्रामर के रूप में कंप्यूटर का उपयोग करते समय, अधिकांश लोगों को तुलनात्मक रूप से> और <के संपर्क में लाया गया था, इनको अक्सर इस तरह के रूप में उजागर किया जाता है।

और <और> के साथ दो ऑपरेंड की तुलना करना संश्लिष्ट है, जिसका अर्थ है

(a > b) == (b < a)

मुझे इनपुट पुनर्निर्देशन के लिए <का उपयोग करते हुए पहली बार याद आया, मुझे डर था

a.sh < file 

के रूप में ही मतलब हो सकता है

file > a.sh

और किसी तरह मेरी a.sh स्क्रिप्ट को ओवरराइट कर दें। शायद यह कई शुरुआती लोगों के लिए एक मुद्दा है।

दुर्लभ अंतर

wc -c journal.txt
15666 journal.txt
cat journal.txt | wc -c 
15666

उत्तरार्द्ध का उपयोग सीधे गणनाओं में किया जा सकता है।

factor $(cat journal.txt | wc -c)

बेशक, फ़ाइल पैरामीटर के बजाय <का उपयोग यहां भी किया जा सकता है:

< journal.txt wc -c 
15666
wc -c < journal.txt
15666
    

लेकिन कौन परवाह करता है - 15k?

अगर मैं कभी-कभी मुद्दों में भाग जाता, तो निश्चित रूप से मैं अपनी बिल्ली को पकड़ने की आदत बदल देता।

बहुत बड़ी या कई, कई फ़ाइलों का उपयोग करते समय, बिल्ली से बचना ठीक है। अधिकांश सवालों के लिए बिल्ली का उपयोग एक विषय नहीं बल्कि ऑर्थोगोनल है।

हर दूसरे शेल विषय पर बिल्ली की चर्चा के इन बेकार उपयोग को शुरू करना केवल कष्टप्रद और उबाऊ है। एक जीवन प्राप्त करें और प्रदर्शन के सवालों से निपटने के दौरान अपनी प्रसिद्धि के मिनट का इंतजार करें।


5
+11111 .. वर्तमान में स्वीकृत उत्तर के लेखक के रूप में, मैं इस रमणीय पूरक की अत्यधिक अनुशंसा करता हूं। विशिष्ट उदाहरण मेरे अक्सर अमूर्त और चिंताजनक तर्कों को स्पष्ट करते हैं, और आपको लेखक के शुरुआती तिहरेपन से जो हंसी मिलती है, file > a.shवह अकेले इस पढ़ने के समय के लायक है :) साझा करने के लिए धन्यवाद!
नेक्रोमन्ट

इस आह्वान में cat file | wc -c, wcEOF तक स्टीन को पढ़ने की जरूरत है, बाइट्स की गिनती। लेकिन इस में wc -c < file, यह सिर्फ स्टड लगाता है, यह किसी भी इनपुट को पढ़ने के बजाय एक नियमित फ़ाइल और प्रिंट st_size है। एक बड़ी फ़ाइल के लिए प्रदर्शन में अंतर स्पष्ट रूप से दिखाई देगा।
22

18

एक अतिरिक्त समस्या यह है कि पाइप चुपचाप एक उपधारा को मुखौटा कर सकता है। इस उदाहरण के लिए, मैं बदल देंगे catसाथ echo, लेकिन एक ही समस्या मौजूद है।

echo "foo" | while read line; do
    x=$line
done

echo "$x"

आप xशामिल होने की उम्मीद कर सकते हैं foo, लेकिन यह नहीं है। xमें एक subshell निष्पादित करने के लिए पैदा की आप सेट था whileपाश। xपाइपलाइन शुरू करने वाले शेल में एक असंबंधित मूल्य होता है, या बिल्कुल सेट नहीं होता है।

Bash4 में, आप कुछ शेल विकल्पों को कॉन्फ़िगर कर सकते हैं ताकि पाइप लाइन की अंतिम कमांड उसी शेल में निष्पादित हो जाए जो पाइप लाइन शुरू करता है, लेकिन तब आप यह कोशिश कर सकते हैं

echo "foo" | while read line; do
    x=$line
done | awk '...'

और xएक बार फिर से स्थानीय है while


5
कड़ाई से POSIX गोले में यह एक मुश्किल समस्या हो सकती है क्योंकि आपके पास पाइप से बचने के लिए यहां तार या प्रक्रिया प्रतिस्थापन नहीं हैं। उस मामले में भी BashFAQ 24 के कुछ उपयोगी समाधान हैं।
कोजिरो

4
में कुछ गोले, सचित्र पाइप एक subshell नहीं बनाता है। उदाहरणों में कॉर्न और जेड शामिल हैं। वे प्रक्रिया प्रतिस्थापन और यहाँ तार का भी समर्थन करते हैं। बेशक वे कड़ाई से POSIX नहीं हैं । बश 4 को shopt -s lastpipeसबस्क्रिप्शन बनाने से बचना है।
अगली सूचना तक रोक दिया गया।

13

जैसा कि कोई है जो नियमित रूप से और कई अन्य शेल प्रोग्रामिंग एंटीपैटर्न को इंगित करता है, मुझे लगता है कि यह बाध्य है, वजन में है।

शेल स्क्रिप्ट बहुत ज्यादा कॉपी / पेस्ट भाषा है। अधिकांश लोग जो शेल स्क्रिप्ट लिखते हैं, वे भाषा सीखने के लिए इसमें नहीं हैं; यह सिर्फ एक बाधा है कि उन्हें भाषा (ओं) में चीजों को जारी रखने के लिए पार करना होगा जो वे वास्तव में कुछ परिचित हैं।

उस संदर्भ में, मैं इसे विघटनकारी के रूप में देखता हूं और संभावित रूप से विभिन्न शेल स्क्रिप्टिंग विरोधी पैटर्न को फैलाने के लिए विनाशकारी भी हूं। कोड जो किसी को स्टैक ओवरफ्लो पर मिलता है, उसे आदर्श रूप से न्यूनतम बदलावों और अपूर्ण समझ के साथ अपने वातावरण में कॉपी / पेस्ट करना संभव होना चाहिए।

नेट पर कई शेल स्क्रिप्टिंग संसाधनों के बीच, स्टैक ओवरफ्लो असामान्य है कि उपयोगकर्ता साइट पर प्रश्नों और उत्तरों को संपादित करके साइट की गुणवत्ता को आकार देने में मदद कर सकते हैं। हालाँकि, कोड संपादन समस्याग्रस्त हो सकता है क्योंकि यह परिवर्तन करना आसान है जो कोड लेखक द्वारा इरादा नहीं किया गया था। इसलिए, हम कोड में परिवर्तन का सुझाव देने के लिए टिप्पणियों को छोड़ देते हैं।

यूयूसीए और संबंधित एंटीपैटर्न टिप्पणियां केवल उस कोड के लेखकों के लिए नहीं हैं, जिस पर हम टिप्पणी करते हैं; वे साइट के पाठकों की मदद करने के लिए उतने ही कैविट एम्प्टर हैं, जितने कोड वे यहां पाते हैं, उनमें समस्याओं के बारे में जानते हैं।

हम ऐसी स्थिति प्राप्त करने की उम्मीद नहीं कर सकते हैं, जहां स्टैक ओवरफ्लो पर कोई उत्तर बेकार catएस (या अछूता चर, या chmod 777अन्य एंटीपार्टन विपत्तियों की एक बड़ी विविधता) की सिफारिश नहीं करता है , लेकिन हम कम से कम उस उपयोगकर्ता को शिक्षित करने में मदद कर सकते हैं जो कॉपी करने के बारे में है / इस कोड को उनकी स्क्रिप्ट के अंतरतम तंग पाश में पेस्ट करें जो लाखों बार निष्पादित होता है।

जहां तक ​​तकनीकी कारणों से जाना जाता है, पारंपरिक ज्ञान यह है कि हमें बाहरी प्रक्रियाओं की संख्या को कम करने की कोशिश करनी चाहिए; शेल स्क्रिप्ट लिखते समय यह एक अच्छे सामान्य मार्गदर्शन के रूप में जारी रहता है।


2
इसके अलावा, बड़ी फ़ाइलों के लिए, पाइपिंग के माध्यम catसे अतिरिक्त संदर्भ स्विच और मेमोरी बैंडविड्थ (और catरीड बफ़र, और पाइप बफ़र्स में डेटा की अतिरिक्त प्रतियों से L3 कैश का प्रदूषण) का एक बहुत कुछ है । विशेष रूप से एक बड़ी मल्टी-कोर मशीन (कई होस्टिंग सेटअपों की तरह) कैश / मेमोरी बैंडविड्थ एक साझा संसाधन है।
पीटर कॉर्ड्स

1
@PeterCordes कृपया अपने माप पोस्ट करें। इसलिए हम कर सकते हैं यदि यह वास्तव में व्यवहार में मायने रखता है। मेरा अनुभव है कि यह आम तौर पर कोई फर्क नहीं पड़ता: oletange.blogspot.com/2013/10/useless-use-of-cat.html
Ole Tange

1
आपका अपना ब्लॉग उच्च-थ्रूपुट के लिए 50% मंदी दिखाता है, और आप कुल थ्रूपुट पर प्रभाव को नहीं देख रहे हैं (यदि आपके पास अन्य कोर रखने में सामान है)। अगर मुझे इसके आसपास मिलता है, तो मैं आपके परीक्षण चला सकता हूं जबकि x264 या x265 सभी कोर का उपयोग करके एक वीडियो एन्कोडिंग कर रहे हैं, और देखें कि यह वीडियो एन्कोडिंग को कितना धीमा करता है। bzip2और gzipसंपीड़न दोनों बहुत धीमी गति से ओवरहेड की मात्रा की तुलना में catअकेले हैं (मशीन के साथ अन्यथा निष्क्रिय)। अपनी तालिकाओं को पढ़ना मुश्किल है (संख्या के मध्य रेखा लपेटें?)। sysसमय बहुत बढ़ जाता है, लेकिन फिर भी छोटा बनाम उपयोगकर्ता या वास्तविक?
पीटर कॉर्डेस

8

मैं अक्सर cat file | myprogramउदाहरणों में उपयोग करता हूं । शायद ही कभी मुझ पर बिल्ली के बेकार उपयोग का आरोप लगाया जा रहा हो ( http://porkmail.org/era/unix/award.html )। मैं निम्नलिखित कारणों से असहमत हूं:

  • यह समझना आसान है कि क्या चल रहा है।

    UNIX कमांड को पढ़ते समय आप एक कमांड की अपेक्षा करते हैं जिसके बाद तर्कों का पुनर्निर्देशन होता है। पुनर्निर्देशन को कहीं भी रखना संभव है, लेकिन यह बहुत कम ही देखा जाता है - इस प्रकार लोगों को उदाहरण पढ़ने में कठिन समय होगा। मेरा मानना ​​है

    cat foo | program1 -o option -b option | program2

    से पढ़ना आसान है

    program1 -o option -b option < foo | program2

    यदि आप शुरू में पुनर्निर्देशन को स्थानांतरित करते हैं तो आप उन लोगों को भ्रमित कर रहे हैं जो इस वाक्य-विन्यास के अभ्यस्त नहीं हैं:

    < foo program1 -o option -b option | program2

    और उदाहरणों को समझना आसान होना चाहिए।

  • इसे बदलना आसान है।

    यदि आप जानते हैं कि कार्यक्रम से पढ़ा जा सकता है cat, तो आप सामान्य रूप से मान सकते हैं कि यह किसी भी प्रोग्राम से आउटपुट को पढ़ सकता है जो STDOUT को आउटपुट करता है, और इस प्रकार आप इसे अपनी आवश्यकताओं के लिए अनुकूलित कर सकते हैं और अनुमानित परिणाम प्राप्त कर सकते हैं।

  • यह जोर देता है कि यदि एसटीडीआईएन एक फ़ाइल नहीं है, तो कार्यक्रम विफल नहीं होता है।

    यह मान लेना सुरक्षित नहीं है कि अगर program1 < fooकाम करता है तो cat foo | program1काम भी करेगा। हालांकि, इसके विपरीत मान लेना सुरक्षित है। यह प्रोग्राम काम करता है यदि STDIN एक फाइल है, लेकिन इनपुट पाइप है, तो यह विफल रहता है, क्योंकि यह खोज का उपयोग करता है:

    # works
    < foo perl -e 'seek(STDIN,1,1) || die;print <STDIN>'
    
    # fails
    cat foo | perl -e 'seek(STDIN,1,1) || die;print <STDIN>'

प्रदर्शन लागत

अतिरिक्त करने की लागत है cat। बेसलाइन ( cat), लो थ्रूपुट ( bzip2), मीडियम थ्रूपुट ( gzip) और हाई थ्रूपुट ( grep) का अनुकरण करने के लिए मैंने कुछ परीक्षण चलाए, इसका अंदाजा लगाने के लिए ।

cat $ISO | cat
< $ISO cat
cat $ISO | bzip2
< $ISO | bzip2
cat $ISO | gzip
< $ISO gzip
cat $ISO | grep no_such_string
< $ISO grep no_such_string

परीक्षण कम अंत प्रणाली (0.6 GHz) और एक साधारण लैपटॉप (2.2 GHz) पर चलाए गए थे। उन्हें प्रत्येक प्रणाली पर 10 बार चलाया गया था और प्रत्येक परीक्षण के लिए इष्टतम स्थिति की नकल करने के लिए सबसे अच्छा समय चुना गया था। $ ISO ubuntu-11.04-desktop-i386.iso था। (यहां प्रीटीयर टेबल: http://oletange.blogspot.com/2013/10/useless-use-of-cat.html )

CPU                       0.6 GHz ARM
Command                   cat $ISO|                        <$ISO                            Diff                             Diff (pct)
Throughput \ Time (ms)    User       Sys        Real       User       Sys        Real       User       Sys        Real       User       Sys        Real
Baseline (cat)                     55      14453      33090         23       6937      33126         32       7516        -36        239        208         99
Low (bzip2)                   1945148      16094    1973754    1941727       5664    1959982       3420      10430      13772        100        284        100
Medium (gzip)                  413914      13383     431812     407016       5477     416760       6898       7906      15052        101        244        103
High (grep no_such_string)      80656      15133      99049      79180       4336      86885       1476      10797      12164        101        349        114

CPU                       Core i7 2.2 GHz
Command                   cat $ISO|           <$ISO             Diff          Diff (pct)
Throughput \ Time (ms)    User     Sys Real   User   Sys Real   User Sys Real User       Sys Real
Baseline (cat)                    0 356    215      1  84     88    0 272  127          0 423  244
Low (bzip2)                  136184 896 136765 136728 160 137131 -545 736 -366         99 560   99
Medium (gzip)                 26564 788  26791  26332 108  26492  232 680  298        100 729  101
High (grep no_such_string)      264 392    483    216  84    304   48 308  179        122 466  158

परिणाम बताते हैं कि निम्न और मध्यम थ्रूपुट के लिए लागत 1% के क्रम में है। यह माप की अनिश्चितता के भीतर अच्छी तरह से है, इसलिए व्यवहार में कोई अंतर नहीं है।

उच्च थ्रूपुट के लिए अंतर बड़ा है और दोनों के बीच स्पष्ट अंतर है।

यह निष्कर्ष की ओर जाता है: आपको <इसके बजाय उपयोग करना चाहिए cat |:

  • प्रसंस्करण की जटिलता एक साधारण grep के समान है
  • प्रदर्शन पठनीयता से अधिक मायने रखता है।

अन्यथा इससे कोई फर्क नहीं पड़ता कि आप उपयोग करते हैं <या नहीं cat |

और इस प्रकार आपको केवल यूयूओसी-पुरस्कार देना चाहिए, यदि और केवल यदि:

  • आप प्रदर्शन में महत्वपूर्ण अंतर माप सकते हैं (पुरस्कार देते समय अपने माप प्रकाशित करें)
  • प्रदर्शन पठनीयता से अधिक मायने रखता है।

-3

मुझे लगता है कि (पारंपरिक तरीके से) पाइप का उपयोग करना थोड़ा अधिक तेज है; मेरे बॉक्स पर मैंने straceयह देखने के लिए कमांड का उपयोग किया कि क्या चल रहा है:

पाइप के बिना:

toc@UnixServer:~$ strace wc -l < wrong_output.c
execve("/usr/bin/wc", ["wc", "-l"], [/* 18 vars */]) = 0
brk(0)                                  = 0x8b50000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77ad000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=29107, ...}) = 0
mmap2(NULL, 29107, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb77a5000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0p\222\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1552584, ...}) = 0
mmap2(NULL, 1563160, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7627000
mmap2(0xb779f000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x178) = 0xb779f000
mmap2(0xb77a2000, 10776, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb77a2000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7626000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb76268d0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xb779f000, 8192, PROT_READ)   = 0
mprotect(0x804f000, 4096, PROT_READ)    = 0
mprotect(0xb77ce000, 4096, PROT_READ)   = 0
munmap(0xb77a5000, 29107)               = 0
brk(0)                                  = 0x8b50000
brk(0x8b71000)                          = 0x8b71000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=5540198, ...}) = 0
mmap2(NULL, 2097152, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7426000
mmap2(NULL, 1507328, PROT_READ, MAP_PRIVATE, 3, 0x2a8) = 0xb72b6000
close(3)                                = 0
open("/usr/share/locale/locale.alias", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=2570, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77ac000
read(3, "# Locale name alias data base.\n#"..., 4096) = 2570
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0xb77ac000, 4096)                = 0
open("/usr/share/locale/fr_FR.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/fr_FR.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/fr_FR/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/fr.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/fr.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/fr/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/fr_FR.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/fr_FR.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/fr_FR/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/fr.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/fr.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/fr/LC_MESSAGES/coreutils.mo", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=316721, ...}) = 0
mmap2(NULL, 316721, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7268000
close(3)                                = 0
open("/usr/lib/i386-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=26064, ...}) = 0
mmap2(NULL, 26064, PROT_READ, MAP_SHARED, 3, 0) = 0xb7261000
close(3)                                = 0
read(0, "#include<stdio.h>\n\nint main(int "..., 16384) = 180
read(0, "", 16384)                      = 0
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7260000
write(1, "13\n", 313
)                     = 3
close(0)                                = 0
close(1)                                = 0
munmap(0xb7260000, 4096)                = 0
close(2)                                = 0
exit_group(0)                           = ?

और पाइप के साथ:

toc@UnixServer:~$ strace cat wrong_output.c | wc -l
execve("/bin/cat", ["cat", "wrong_output.c"], [/* 18 vars */]) = 0
brk(0)                                  = 0xa017000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb774b000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=29107, ...}) = 0
mmap2(NULL, 29107, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7743000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0p\222\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1552584, ...}) = 0
mmap2(NULL, 1563160, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb75c5000
mmap2(0xb773d000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x178) = 0xb773d000
mmap2(0xb7740000, 10776, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7740000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb75c4000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb75c48d0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xb773d000, 8192, PROT_READ)   = 0
mprotect(0x8051000, 4096, PROT_READ)    = 0
mprotect(0xb776c000, 4096, PROT_READ)   = 0
munmap(0xb7743000, 29107)               = 0
brk(0)                                  = 0xa017000
brk(0xa038000)                          = 0xa038000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=5540198, ...}) = 0
mmap2(NULL, 2097152, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb73c4000
mmap2(NULL, 1507328, PROT_READ, MAP_PRIVATE, 3, 0x2a8) = 0xb7254000
close(3)                                = 0
fstat64(1, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
open("wrong_output.c", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0664, st_size=180, ...}) = 0
read(3, "#include<stdio.h>\n\nint main(int "..., 32768) = 180
write(1, "#include<stdio.h>\n\nint main(int "..., 180) = 180
read(3, "", 32768)                      = 0
close(3)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
13

आप के साथ कुछ परीक्षण कर सकते हैं straceऔर timeअच्छा बेंच मार्किंग के लिए और अधिक और लंबे समय तक आदेशों के साथ आदेश।


9
मुझे समझ में नहीं आ रहा है कि आप (पारंपरिक तरीके से) पाइप का उपयोग करने का क्या मतलब है , या आपको क्यों लगता है कि यह straceदिखाता है कि यह तेज़ है - दूसरे मामले में निष्पादन का straceपता नहीं लगा रहा है wc -l। यह केवल यहाँ पाइपलाइन की पहली कमांड का पता लगाता है।
कोजिरो

@ कोकोजी: मेरा मतलब पारंपरिक तरीके से है = सबसे ज्यादा इस्तेमाल किया जाने वाला तरीका (मुझे लगता है कि हम अप्रत्यक्ष की तुलना में अधिक पाइप का उपयोग करते हैं), मैं पुष्टि नहीं कर सकता कि यह तेज है या नहीं, मेरे ट्रेस में मैंने अप्रत्यक्ष के लिए अधिक सिस्टम कॉल देखा। अधिक समय लेने के साथ आप एसी प्रोग्राम और लूप का उपयोग कर सकते हैं। यदि आप रुचि रखते हैं तो हम इसे यहाँ रख सकते हैं :)
TOC

3
एक सेब से सेब की तुलना strace -f sh -c 'wc -l < wrong_output.c'साथ-साथ होगी strace -f sh -c 'cat wrong_output.c | wc -l'
चार्ल्स डफी

5
यहाँ ideone.com के परिणाम हैं, जो वर्तमान में स्पष्ट रूप से इसके पक्ष में हैं cat: ideone.com/2w1W42#stderr
tripleee

1
@CharlesDuffy: mkfifoएक नामित पाइप बनाता है । एक अनाम पाइप के साथ स्थापित किया जाता है pipe(2)और फिर फोर्किंग, और माता-पिता और बच्चे के पास पाइप के अलग-अलग छोर होते हैं। लेकिन हां, यह उत्तर कुल बकवास है, और सिस्टम कॉल या strace -Oओवरहेड को मापने के लिए उपयोग करने की कोशिश भी नहीं की , या -rअंतिम के सापेक्ष प्रत्येक कॉल को टाइमस्टैम्प करने के लिए ...
पीटर कॉर्डेस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.