जवाबों:
grep -l string2 `grep -l string1 /path/*`
जो जैसा है वैसा है
grep -l string2 $(grep -l string1 /path/*)
संपादित करें: grep string1 /path/* | grep string2विधर्मियां ऐसा क्यों नहीं करती हैं जो मुझे लगता है कि alwbtc चाहता है।
$ cd /tmp
$ cat a
apples
oranges
bananas
$ cat b
apples
mangoes
lemons
$ cat c
mangoes
limes
pears
$ cd ~
$ grep apples /tmp/* | grep mangoes
$
कुछ भी नहीं मिला, लेकिन फ़ाइल बी में दोनों तार हैं।
यहाँ मुझे लगता है कि alwbtc क्या चाहता है
$ grep -l apples $(grep -l mangoes /tmp/*)
/tmp/b
-lदोनों आदेशों को समान मानने के लिए एक विकल्प याद किया ।
एक पाइप grepको दूसरे में डालें:
grep "string1" /path/to/files/* | grep "string2"
यहाँ बराबर है एसीकेRedGrittyBrick के उत्तर की कमान :
ack string2 $(ack string1 -l)
उसी तरीके से काम करता है ( ackडिफ़ॉल्ट रूप से वर्तमान निर्देशिका को पुन: खोजता है)। $()खोज के भीतर की सामग्री string1लेकिन -lकेवल उन फ़ाइलनामों को आउटपुट करती है जहां वह स्ट्रिंग पाई गई थी। फिर उन्हें बाहरी कमांड में तर्क के रूप में पारित किया जाता है, जिसका अर्थ string2केवल फाइलों की सूची के भीतर खोजा जाता है।
comm -12 <(grep --fixed-strings --files-with-matches "STRING1" /path/to/files/* 2>/dev/null | sort) <(grep --fixed-strings --files-with-matches "STRING1" /path/to/files/* 2>/dev/null | sort)
या कम अतिरेक से:
search_files () { str="$1"; shift; grep -Fl "$str" "$@" 2>/dev/null | sort; }
comm -12 <(search_files "STRING1" /path/to/files/*) <(sf "STRING2" /path/to/files/*)
यह तब काम करेगा जब तार एक ही फाइल की अलग-अलग लाइनों पर हों और अगर फ़ाइल नाम में से कोई एक तार हो तो भी झूठी सकारात्मकता से बचेंगे।
@ RedGrittyBrick के समाधान के बारे में विस्तार से बताने के लिए, जो कि कमांड में अनअटेंडेड प्लस को चलाने के दौरान त्रुटि को कम करने के लिए अप्रतिष्ठित चल रहा है और इच्छित फ़ाइलों को खोजने के लिए आपको पुन: विचार करना चाहिए।
grep -l 'STRING1' $(! grep -lrs 'STRING2' /absolute/path/to/search/dir && echo /dev/null)
-sविकल्प त्रुटि संदेशों को दबा देगा
-rविकल्प मनमाने ढंग से नेस्टेड निर्देशिकाओं में स्ट्रिंग की खोज करने की अनुमति देता है जो कि गारंटी
!के साथ संयुक्त है && echo /dev/nullकि कमांड लटका नहीं होगा। अन्यथा, अगर inner grepकोई फ़ाइल नहीं मिलती है तो वह कुछ भी आउटपुट नहीं करेगी जिससे कि outer grepअनिश्चित काल तक खोज पर इनपुट का इंतजार रहेगा। यह समाधान आउटपुट /dev/nullइन मामलों में तो outer grepके लिए खोज करेंगे STRING1में /dev/nullजहां यह कुछ भी नहीं मिल चाहिए था।
मैं 2 या अधिक स्ट्रिंग्स करने के लिए एक एक्स्टेंसिबल तरीके की तलाश में था और इसके साथ आया:
grep -rl string1 path-to-files | xargs grep -l string2 | xargs grep -l string3
पहला grep पुनरावर्ती रूप से फ़ाइलों के नाम को खोजता string1है path-to-files।
परिणामों को पाइप किया जाता है xargsजिसमें उन फ़ाइलों पर एक या अधिक grep कमांड चलता है string2।
इसके बाद परिणाम को दूसरी xargsकमांड में डाला जाता है string3- यह पहली xargsकॉल के समान है , लेकिन एक अलग स्ट्रिंग की तलाश में है।
xargsवसीयत के उपयोग से उन समस्याओं से बचा जा सकता है जहां बहुत सारे परिणाम हैं जो बैक-टिक्स के उपयोग से परिणामी कमांड लाइन बहुत लंबी है।
चेतावनी हम अनुप्रेषित कर सकते हैं से बचने के लिए stderrकरने के लिए /dev/null:
grep -rl string1 path-to-files 2>/dev/null | xargs grep -l string2
बाद के grep कॉल पर इसकी आवश्यकता नहीं है क्योंकि string1फ़ाइल के अंदर पहले से ही पाया गया है इसलिए अनुमतियाँ अच्छी हैं।
-lलाइनों के बजाय फ़ाइल नामों को वापस करने के विकल्प का उपयोग कर रहे हैं। फिर वह उस सूची कोFILEदूसरे grep में तर्क के रूप में पारित करने के लिए डॉलर चिह्न या पीछे के उद्धरण का उपयोग कर रहा है । यह दूसरे grep को प्रत्येक फ़ाइल की संपूर्णता की खोज करने की अनुमति देता है जो मेरे समाधान के अनुसार व्यक्तिगत लाइनों के बजाय मिली है।