मैं एक पाइप कैसे शामिल करूं | मेरे लिनक्स में -exec कमांड खोजें?


220

यह काम नहीं कर रहा है। क्या इसे खोजने में किया जा सकता है? या मुझे xargs की आवश्यकता है?

find -name 'file_*' -follow -type f -exec zcat {} \| agrep -dEOE 'grep' \;

जवाबों:


144

कई प्रक्रियाओं को चलाने और एक प्रक्रिया के आउटपुट को किसी अन्य प्रक्रिया के इनपुट में पाइप के रूप में पाइप के प्रतीक की व्याख्या करने का काम शेल (/ बिन / श या समकक्ष) की जिम्मेदारी है।

अपने उदाहरण में आप या तो पाइपिंग करने के लिए अपने शीर्ष स्तर के खोल का उपयोग कर सकते हैं:

find -name 'file_*' -follow -type f -exec zcat {} \; | agrep -dEOE 'grep'

कार्यकुशलता के संदर्भ में इस परिणाम में खोज का एक आह्वान, zcat के कई आह्वान, और agrep का एक आह्वान शामिल है।

इसके परिणामस्वरूप केवल एक एग्रेप प्रक्रिया को जन्म दिया जाता है, जो कि zcat के कई आह्वान द्वारा उत्पादित सभी उत्पादन को संसाधित करेगा।

यदि आप किसी कारण से कई बार agrep को आमंत्रित करना चाहते हैं, तो आप कर सकते हैं:

find . -name 'file_*' -follow -type f \
    -printf "zcat %p | agrep -dEOE 'grep'\n" | sh

यह निष्पादित करने के लिए पाइप का उपयोग करते हुए आदेशों की एक सूची का निर्माण करता है, फिर उन्हें वास्तव में निष्पादित करने के लिए एक नए शेल में भेजता है। (अंतिम "O | शिम" को इस तरह कमांड लाइन के डिबग या ड्राई रन करने का अच्छा तरीका है।)

दक्षता के संदर्भ में इस परिणाम में खोज का एक आह्वान, श का एक आह्वान, zcat के कई आह्वान और agrep के कई आह्वान शामिल हैं।

आदेश की संख्या के संदर्भ में सबसे कुशल समाधान पॉल टॉम्बलिन का सुझाव है:

find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'

... जिसे खोजने में एक आह्वान, एक झटके का आह्वान, zcat के कुछ आह्वान और agrep के एक आह्वान का खर्च आता है।


1
Xargs का एक और फायदा यह होगा कि, आप इसे पी-स्विच (-0) का उपयोग करके आधुनिक मल्टी कोर सीपीयू के साथ और भी अधिक गति प्रदान कर सकते हैं।
23

हां, सामान्य रूप से निष्पादन में तेजी लाने के लिए -P- स्विच वास्तव में एक अच्छा तरीका है। दुर्भाग्य से, आप समानांतर zcat प्रक्रियाओं के उत्पादन के जोखिम को agrep interleaved में पाइप किया जा रहा है, जो परिणाम को प्रभावित करेगा। इस आशय का उपयोग करके प्रदर्शित किया जा सकता है: इको-ई "1 \ n2" | xargs -P 0 -n 1 हाँ | uniq
रॉल्फ डब्ल्यू रासमुसेन

@ अदम, मैंने आपका सुझाया बदलाव किया है।
पॉल टॉम्बलिन

जिसके लिए आप शानदार xjobs कमांड (मूल रूप से सोलारिस से) स्थापित कर सकते हैं
22:13 पर 22:13

4
एक सरल और अधिक सामान्य जवाब में है stackoverflow.com/a/21825690/42973 : -exec sh -c "… | … " \;
एरिक ओ लेबिगॉट

277

समाधान आसान है: श के माध्यम से निष्पादित करें

... -exec sh -c "zcat {} | agrep -dEOE 'grep' " \;

17
ओपी जो पूरा करने की कोशिश कर रहा था उसे ऊपर दिए गए सुझावों के साथ पूरा किया जा सकता है, लेकिन यह वही है जो वास्तव में पूछे गए सवाल का जवाब देता है। इसे इस तरह से करने के कारण हैं - निष्पादन केवल फाइलों द्वारा संचालित होने की तुलना में बहुत अधिक शक्तिशाली है, विशेषकर जब परीक्षण के साथ संयुक्त रूप से मिला। उदाहरण के लिए: geda-gaf / -type d -exec bash -c 'DIR = {}; $ उस खोज पथ में सभी निर्देशिकाओं को वापस कर देगा जिसमें उस निर्देशिका की सभी फाइलों के बीच कुल 5 पंक्तियाँ हैं जिनमें शब्द मसाला है
swarfrat

3
सबसे बढ़िया उत्तर। पूरे आउटपुट को टटोलना (जैसा कि अन्य उत्तर बताते हैं) प्रत्येक फ़ाइल को grep के समान नहीं है। युक्ति: श के बजाय, आप अपने इच्छित किसी अन्य शेल का उपयोग कर सकते हैं (मैंने कोशिश की कि बैश के साथ और यह ठीक चल रहा है)।
पग्लियुका

1
-cविकल्प की अनदेखी न करें । अन्यथा आपको एक puzzling No such file or directoryत्रुटि संदेश मिलेगा ।
अस्माइर

यहाँ एक महान ps प्रतिस्थापन है जो एक निष्पादन शेल के अंदर पाइपिंग के साथ खोज का उपयोग करता है: / usr / bin / find / proc -mindepth 1 -maxdepth 1 -type d -regex '। * / [0-9+ +' - -। Print -exec bash -c "cat {} / cmdline | tr '\\ 0' ''; echo" \;
२/११ बजे

1
फ़ाइलों को खोजने और नियमित अभिव्यक्ति का उपयोग करके उन्हें sed के साथ नाम बदलने का उदाहरणfind -type f -name '*.mdds' -exec sh -c "echo {} | sed -e 's/_[0-9]\+//g' | xargs mv {}" \;
रोस्तफ्रेई

16
find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'

दक्षता कारणों के लिए -प्रिंट और xargs से बचने की उम्मीद करना। हो सकता है कि यह वास्तव में मेरी समस्या है: खोजने के लिए पाइप कमांड के माध्यम से संभाल नहीं कर सकते हैं
someguy

यह उनके नाम के रिक्त स्थान वाली फ़ाइलों के साथ काम नहीं करता है; ठीक करने के लिए -print0 के साथ -प्रिंट को बदलें और xargs के लिए -0 विकल्प जोड़ें
एडम रोसेनफील्ड

2
@someguy - Wha? दक्षता कारणों से xargs से बचना? Zcat के एक उदाहरण को कॉल करना, और इसे कई फ़ाइलों की सूची में पास करना, प्रत्येक पाए गए फ़ाइल के लिए एक नई आवृत्ति को निष्पादित करने की तुलना में कहीं अधिक कुशल है।
शेरम पेंडले

@ अदम - मैंने आपका सुझाया बदलाव किया है। उस समय का 99% जब मैं खोज रहा हूं, यह मेरे स्रोत कोड निर्देशिकाओं में है, और फाइलों में से कोई भी स्थान नहीं है इसलिए मैं Print0 के साथ परेशान नहीं करता हूं। अब मेरे दस्तावेज़ निर्देशिका, दूसरी ओर, मुझे प्रिंट 0 याद है।
पॉल टॉम्बलिन

10

आप एक whileलूप पर भी पाइप कर सकते हैं जो उस फ़ाइल पर कई क्रियाएं कर सकता है जो findलोकेट करता है। तो यहाँ फ़ाइलों jarकी एक बड़ी distro के साथ फ़ोल्डर में किसी दिए गए java क्लास फ़ाइल के लिए अभिलेखागार में देखने के लिए एक हैjar

find /usr/lib/eclipse/plugins -type f -name \*.jar | while read jar; do echo $jar; jar tf $jar | fgrep IObservableList ; done

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

/usr/lib/eclipse/plugins/org.eclipse.core.contenttype.source_3.4.1.R35x_v20090826-0451.jar/usr/lib/eclipse/plugins/org.eclipse.core.databinding.observinding_1.2.0.M200902-0902 .jar org / eclipse / core / databinding / observable / list / IObservableLLclclass /usr/lib/eclipse/plugins/ org.eclipse.search.source.ch3 / 5.1.r351_v20090708-0800.jar / usr / lib / plugins / करें। org.eclipse.jdt.apt.core.source_3.3.202.R35x_v20091130-2300.jar/usr/lib/eclipse/plugins/org.eclipse.cv.source_1.0.400.v201002111343.jar / usr / lib / plugins / org.eclipse.help.appserver_3.1.400.v20090429_1800.jar

मेरे बैश शेल (xubuntu10.04 / xfce) में यह मिलान fgrepकिए गए स्ट्रिंग को हाइलाइट करने के रूप में मिलान किए गए क्लासनाम को बोल्ड बनाता है ; यह उन सैकड़ों jarफ़ाइलों की सूची को स्कैन करना वास्तव में आसान बनाता है जिन्हें खोजा गया था और आसानी से कोई भी मैच देख सकता था।

खिड़कियों पर आप एक ही काम कर सकते हैं:

for /R %j in (*.jar) do @echo %j & @jar tf %j | findstr IObservableList

ध्यान दें कि विंडोज़ में कमांड विभाजक 'और' नहीं 'है;' और यह कि '@' ठीक उसी तरह टंकल आउटपुट देने के लिए कमांड की प्रतिध्वनि को दबाता है, जैसे कि लिनक्स ऊपर आउटपुट खोजता है; हालाँकि findstr, मिलान किए गए स्ट्रिंग को बोल्ड नहीं बनाता है, इसलिए आपको मिलान किए गए वर्ग नाम को देखने के लिए आउटपुट पर थोड़ा करीब देखना होगा। यह पता चला है कि 'कमांड' के लिए विंडोज़ '' बहुत कुछ ट्रिक्स जानता है जैसे टेक्स्ट फाइल के माध्यम से लूपिंग ...

का आनंद लें


2

मैंने पाया कि एक स्ट्रिंग शेल कमांड (sh -c) सबसे अच्छा काम करता है, उदाहरण के लिए:

find -name 'file_*' -follow -type f -exec bash -c "zcat \"{}\" | agrep -dEOE 'grep'" \;

0

यदि आप एक सरल विकल्प की तलाश कर रहे हैं, तो यह एक लूप का उपयोग करके किया जा सकता है:

for i in $(find -name 'file_*' -follow -type f);do zcat $i | agrep -dEOE 'grep');done

या, अधिक सामान्य और समझने में आसान रूप:

for i in $(YOUR_FIND_COMMAND);do YOUR_EXEC_COMMAND_AND_PIPES );done

और किसी भी {} को i_EXEC_COMMAND_AND_PIPES में $ i से बदल दें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.