मैं उन फ़ाइलों को कैसे खोज सकता हूं जिनमें दिए गए स्ट्रिंग पैटर्न नहीं हैं?


535

कैसे मैं कैसे पता फ़ाइलें वर्तमान निर्देशिका जो है में नहीं शब्द शामिल foo(का उपयोग करते हुए grep)?

जवाबों:


817

यदि आपके grep में विकल्प -L(या --files-without-match) है:

$ grep -L "foo" *

1
जैसा कि कहीं और बताया गया है कि ऐक डिफ़ॉल्ट रूप से .svn (तोड़फोड़) फाइलों से बचने में मदद करता है।
गुरु

11
@ GuruM यह चर निर्यात करके GNU grep में किया जा सकता है GREP_OPTIONS='--exclude-dir=.svn --exclude-dir=.git': ^)
bufh

6
या ag का उपयोग करते हुए समतुल्य :ag -L 'foo'
बिशप

5
जादू की तरह काम करता है! संकेत: मैच उपनिर्देशिकाओं के -rLबजाय का उपयोग करें-L
Ufos

1
@ लॉरी - ग्लोबिंग समस्याओं से बचने के लिए एक क्लीनर तरीका "खाली" लंबे विकल्प का उपयोग करना है: grep -L 'foo' -- *मानक यह है कि कमांड जो यह --इंगित करने के लिए लंबे विकल्प का उपयोग करते हैं कि इस बिंदु के बाद और कोई विकल्प नहीं हैं।
धान लांडऊ

44

देख लेना ack। यह करता है.svn स्वचालित रूप से आपके लिए बहिष्करण , आपको पर्ल को नियमित अभिव्यक्ति देता है, और एकल पर्ल प्रोग्राम का एक सरल डाउनलोड है।

आप जो देख रहे हैं उसके बराबर होना चाहिए ack:

ack -L foo

23

आप इसे grep के साथ अकेले (बिना खोजे) कर सकते हैं।

grep -riL "foo" .

यह उपयोग किए गए मापदंडों का स्पष्टीकरण है grep

     -L, --files-without-match
             each file processed.
     -R, -r, --recursive
             Recursively search subdirectories listed.

     -i, --ignore-case
             Perform case insensitive matching.

यदि आप उपयोग करते हैं l(कम किया हुआ) तो आपको विपरीत (मैचों के साथ फाइल) मिलेगा

     -l, --files-with-matches
             Only the names of files containing selected lines are written

17

निम्न आदेश मुझे वह सभी फ़ाइल देता है जिसमें पैटर्न नहीं है foo:

find .  -not  -ipath '.*svn*' -exec  grep  -H -E -o -c  "foo"  {} \; | grep 0

4
आप grep 0 $ के अंत में grep 0 बदलना चाहते हैं (अन्यथा आपको फ़ाइलों पर गलत मेल मिलते हैं जिनके वर्ण 0 उनके फ़ाइल नाम में हैं)।
क्लूसो

9
@clouseau ज्यादातर सही है ... हालांकि, grep '0$'10 लाइनों के गुणकों के साथ फ़ाइलों का मिलान भी करेगा! आपको grep ':0$'पंक्ति के अंत में एक स्पष्ट ': 0' की जांच करने के लिए अंत में आवश्यकता है । तब आपको केवल शून्य लाइनों से मेल खाने वाली फाइलें मिलेंगी।
त्रिनिट्रॉनएक्स

UNIX मैं इन विकल्पों के साथ खोज या grep का संस्करण नहीं है, इसलिए मुझे अन्य टिप्पणियों में सुझाए गए "ack" कमांड के साथ जाना पड़ा।
केसी बाल्ट्ज

14

निम्न आदेश svnएक दूसरे का उपयोग करके फ़ोल्डर्स को फ़िल्टर करने के लिए खोज की आवश्यकता को बाहर करता है grep

grep -rL "foo" ./* | grep -v "\.svn"


6

मेरा सौभाग्य था

grep -H -E -o -c "foo" */*/*.ext | grep ext:0

मेरे प्रयासों grep -vने मुझे "फू" के बिना ही सारी लाइनें दीं।


4

मुसीबत

मुझे एक बड़ी परियोजना को फिर से शुरू करने की आवश्यकता है जो .phtmlइनलाइन PHP कोड का उपयोग करके HTML को लिखने के लिए फ़ाइलों का उपयोग करता है । मैं इसके बजाय मूंछ टेम्पलेट का उपयोग करना चाहता हूं । मैं ऐसे किसी भी .phtmlगाइल्स को ढूंढना चाहता हूं, जिनमें तार न हों new Mustacheक्योंकि इन्हें फिर से लिखने की जरूरत है।

समाधान

find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'

व्याख्या

पाइप से पहले:

खोज

find . इस निर्देशिका में शुरू होने वाली फ़ाइलों को पुन: प्राप्त करें

-iname '*.phtml'फ़ाइल नाम में .phtml( होना चाहिए)i यह केस-असंवेदनशील बनाता है)

-exec 'grep -H -E -o -c 'new Mustache' {}'grepप्रत्येक मिलान किए गए पथ पर कमांड चलाएँ

ग्रेप

-H हमेशा उत्पादन लाइनों के साथ फ़ाइल नाम हेडर प्रिंट करें।

-E एक विस्तारित नियमित अभिव्यक्ति के रूप में पैटर्न की व्याख्या करें (जैसे कि उदाहरण के लिए व्यवहार करने के लिए बल grep)।

-o लाइनों के मिलान वाले हिस्से को ही प्रिंट करता है।

-c केवल चयनित लाइनों की एक गिनती मानक आउटपुट के लिए लिखी जाती है।


यह मुझे समाप्त होने वाले सभी फ़ाइल पथों की सूची देगा .phtml, new Mustacheजिनमें से प्रत्येक में स्ट्रिंग की संख्या की गणना होती है।

$> find . -iname '*.phtml$' -exec 'grep -H -E -o -c 'new Mustache' {}'\;

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/orders.phtml:1
./app/MyApp/Customer/View/Account/banking.phtml:1
./app/MyApp/Customer/View/Account/applycomplete.phtml:1
./app/MyApp/Customer/View/Account/catalogue.phtml:1
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0

पहली पाइप grep :0$इस सूची को फ़िल्टर करती है जिसमें केवल समाप्त होने वाली लाइनें शामिल हैं :0:

$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0

दूसरी पाइप sed 's/..$//'प्रत्येक पंक्ति के अंतिम दो वर्णों को छीन लेती है, बस फ़ाइल पथ छोड़ती है।

$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml
./app/MyApp/Customer/View/Account/studio.phtml
./app/MyApp/Customer/View/Account/classadd.phtml
./app/MyApp/Customer/View/Account/orders-trade.phtml

3

यदि आप git का उपयोग कर रहे हैं, तो यह सभी ट्रैक की गई फ़ाइलों को खोजता है:

git grep -L "foo"

और यदि आप ** उपनिर्देशिका ग्लोबिंग चालू कर दिया है पर नज़र रखी फाइलों के सबसेट में खोज कर सकते हैं ( shopt -s globstar.bashrc में, देखने के इस ):

git grep -L "foo" -- **/*.cpp

1

मेरे grep के पास कोई -L विकल्प नहीं है। मैं इसे प्राप्त करने के लिए वर्कअराउंड ढूंढता हूं।

विचार हैं:

  1. सभी फ़ाइल नाम को डंप करने के लिए योग्य स्ट्रिंग को dxt1.txt पर डंप करें।
  2. निर्देशिका में सभी फ़ाइल नाम को txt2.txt पर डंप करें।
  3. अलग कमांड के साथ 2 डंप फ़ाइल के बीच अंतर करें।

    grep 'foo' *.log | cut -c1-14 | uniq > txt1.txt
    grep * *.log | cut -c1-14 | uniq > txt2.txt
    diff txt1.txt txt2.txt | grep ">"
    

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

1

find *20161109* -mtime -2|grep -vwE "(TRIGGER)"

आप "खोज" के तहत फ़िल्टर और "grep -vwE" के तहत बहिष्करण स्ट्रिंग निर्दिष्ट कर सकते हैं। यदि आपको संशोधित समय पर भी फ़िल्टर करने की आवश्यकता हो, तो माइम का उपयोग करें।


यह मुझे स्ट्रिंग के बिना सभी लाइनों को दिखाने के लिए लगता है, ओपी सिर्फ फ़ाइल नामों के लिए पूछता है।
बेन किसान

1

बग रिपोर्ट खोलें

जैसा कि @tukan ने टिप्पणी की है, Ag के लिए एक खुला बग रिपोर्ट है -L/ --files-without-matchesझंडा के बारे में :

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

इस पर कोई अपडेट? -Lपूरी तरह से फ़ाइल की पहली पंक्ति पर मेल को अनदेखा करता है। लगता है जैसे कि यह जल्द ही तय नहीं होने वाला है, ध्वज को पूरी तरह से हटा दिया जाना चाहिए, क्योंकि यह प्रभावी रूप से विज्ञापन के रूप में काम नहीं करता है


रजत खोजकर्ता - Ag (इच्छित कार्य - बग रिपोर्ट देखें)

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

एक कोड खोज टूल, जो गति पर ध्यान केंद्रित करने के साथ, एक समान है।

देखते हुए man ag, हम विकल्प -Lया --files-without-matchesविकल्प ढूंढते हैं:

...

OPTIONS
    ...

    -L --files-without-matches
           Only print the names of files that don´t contain matches.

यानी, के लिए रिकर्सिवली फ़ाइलों को मेल नहीं खाते के लिए खोज fooवर्तमान निर्देशिका से,:

ag -L foo

केवल मेल खाने वाली फ़ाइलों के लिए वर्तमान निर्देशिका को खोजने के लिए foo, केवल --depth=0पुनरावृत्ति के लिए निर्दिष्ट करें :

ag -L foo --depth 0

यह -Lबग के कारण समय-समय पर विफल रहता है - github.com/ggreer/the_silver_searcher/issues/238
tukan

@tukan शीघ्र के लिए धन्यवाद। मैंने उत्तर को अपडेट कर दिया है; उत्तर को हटाने के लिए नहीं बल्कि बग के बारे में जानकारी के साथ खोलने का चयन करना।
dfri

1

एक और विकल्प जब grep के पास -L विकल्प (उदाहरण के लिए IBM AIX) नहीं है, बिना grep और शेल के कुछ भी नहीं:

for file in * ; do grep -q 'my_pattern' $file || echo $file ; done

-4
grep -irnw "filepath" -ve "pattern"

या

grep -ve "pattern" < file

उपरोक्त आदेश हमें परिणाम देगा-जैसे कि खोजे जा रहे पैटर्न के व्युत्क्रम को खोजता है


1
यह उन पंक्तियों को प्रिंट करता है जिनमें पैटर्न नहीं होता है। आप -lकेवल फ़ाइल नाम मुद्रित करने के लिए विकल्प जोड़ सकते हैं ; लेकिन यह अभी भी किसी भी फ़ाइल के नाम को प्रिंट करता है जिसमें कोई भी रेखा होती है जिसमें पैटर्न नहीं होता है। मेरा मानना ​​है कि ओपी उन फाइलों को खोजना चाहता है जिनमें कोई भी रेखा नहीं होती है जिसमें पैटर्न होता है।
ट्रिपलए

कमांड आपने "फाइलपाथ" में उनकी सभी लाइनों के साथ सूचियां प्रदान की हैं जिसमें "पैटर्न" नहीं है।
एप्रोडान

-6

निम्न आदेश आपको उन पंक्तियों को फ़िल्टर करने में मदद कर सकता है जिनमें "फू" के विकल्प शामिल हैं।

cat file | grep -v "foo"

2
यह उन लाइनों को प्रिंट करता है जो मेल नहीं खातीं, उन फाइलों के नाम नहीं हैं जिनमें किसी भी लाइन पर मैच नहीं है। चोट के अपमान को जोड़ने के लिए, यह एक बेकार उपयोग केcat रूप में है
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.