किसी विशिष्ट पथ में फ़ाइल को छोड़कर `grep` चलाएँ


12

मैं ./test/main.cppअपनी खोज से फ़ाइल को बाहर करना चाहता हूं।

यहाँ मैं देख रहा हूँ:

$ grep -r pattern --exclude=./test/main.cpp
./test/main.cpp:pattern
./lib/main.cpp:pattern
./src/main.cpp:pattern

मुझे पता है कि पाइप-एंड-फिल्टर व्यवस्था में कई कमांडों का उपयोग करके मुझे जो आउटपुट चाहिए, वह संभव है, लेकिन क्या कुछ उद्धृत / बच grepरहा है जो समझ जाएगा कि मैं मूल रूप से क्या चाहता हूं?


आउटपुट को फ़िल्टर करने पर आधारित एक समाधान अच्छी तरह से पैमाने पर नहीं होता है क्योंकि यह संबंधित परिणामों को बाहर करने से पहले फ़ाइल को अनावश्यक रूप से खोजता है। यदि मैं संपूर्ण निर्देशिका (के साथ --exclude-dir) को बाहर करना चाहता हूं तो समस्या बढ़ जाती है । इसलिए मैं grep को मूल रूप से बहिष्करण प्रदर्शन करना चाहता हूं।
नोबार

1
--exclude निर्दिष्ट एक रास्ता नहीं glob
PersianGulf

जवाबों:


6

grep यदि आप अलग-अलग निर्देशिकाओं में एक ही नाम के साथ अधिक फ़ाइलें हैं, तो इसके बजाय खोज का उपयोग करें: एक निश्चित निर्देशिका में फ़ाइल के लिए ऐसा नहीं कर सकते

find . -type f \! -path './test/main.cpp' -exec grep pattern {} \+


तुम क्यों बचने कर रहे हैं \!और \+? यह backslashes के बिना ठीक काम करने लगता है।
nobar

@nobar मैं इसका उपयोग कर रहा हूं क्योंकि कुछ वर्ण शेल कीवर्ड हैं इसलिए आप कभी भी आश्चर्यचकित नहीं होंगे क्योंकि यदि वे बच गए तो कुछ भी नहीं हो सकता है।
मीकलह

" grepयह नहीं कर सकते, findइसके बजाय का उपयोग करें " - सही।
नोबार

4

मुझे नहीं लगता कि यह GNU के साथ संभव है grep। हालांकि आपको पाइप की जरूरत नहीं है।

के साथ find:

find . ! -path ./test/main.cpp -type f -exec grep pattern {} +

के साथ zsh:

grep pattern ./**/*~./test/main.cpp(.)

(छिपी हुई फ़ाइलों को बाहर करता है, साथ ही .it, .svn ... को बाहर करने के लिए)।


2

मैं एक किताब लिख सकता था: "खोई हुई कला xargs"। find ... -exec … ';शुरूआत प्रत्येक फ़ाइल के लिए एक ग्रेप (लेकिन साथ संस्करण -exec … +नहीं करता है)। ठीक है, हम इन दिनों सीपीयू चक्र बर्बाद कर रहे हैं तो क्यों नहीं, है ना? लेकिन अगर प्रदर्शन और स्मृति और शक्ति एक मुद्दा है: xargs का उपयोग करें:

find . -type f \! -path 'EXCLUDE-FILE' -print0 | xargs -r0 grep 'PATTERN'

जीएनयू की findहै -print0जाएगा NULइसके उत्पादन और -terminate xargs' -0इनपुट के रूप में है कि प्रारूप विकल्प सम्मान। यह सुनिश्चित करता है कि आपकी फ़ाइल में जो भी मज़ेदार पात्र हैं, पाइपलाइन भ्रमित नहीं होगी। -rविकल्प यकीन है कि वहाँ इस मामले में कोई त्रुटि है बनाता है findपाता कुछ भी नहीं।

ध्यान दें, अब आप निम्न कार्य कर सकते हैं:

find . -type f -print0 | grep -z -v "FILENAME EXCLUDE PATTERN" | 
  xargs -r0 grep 'PATTERN'

जीएनयू ग्रीप एक्सरे के -zसमान ही काम करता है -0


3
कुछ दिलचस्प नोट्स, लेकिन मुझे यकीन नहीं है कि आप प्रदर्शन के मुद्दे के बारे में सही हैं। जैसा कि मैं समझता हूं कि यह find -exec (cmd) {} +उसी तरह काम करता है xargsऔर जैसा find -exec (cmd) {} \;काम करता है xargs -n1। दूसरे शब्दों में, आपका कथन केवल तभी सही है जब \;संस्करण का उपयोग किया जाता है।
नोबार

3
xargsउपयोग करने की तुलना में पाइपिंग कम कुशल है -exec … +(यद्यपि मामूली रूप से)। यहाँ कोई भी उत्तर का उल्लेख नहीं करता है -exec … \;
गिलेस एसओ- बुराई को रोकना

1
खैर, एस - टी। मैं खुद को डेट करता हूं। टिप्पणी और सुधार के लिए धन्यवाद। मुझे लगा कि the + एक टाइपो था। ओह देखो, -exec ... +जनवरी 2005 में जोड़ा गया। हाँ, मैं पुराना नहीं हूँ ... बिल्कुल ...।
ओथियस

2

यदि आपका findसमर्थन -path2008 में POSIX में जोड़ा गया था, लेकिन सोलारिस में अभी भी गायब है:

find . ! -path ./test/main.cpp -type f -exec grep pattern /dev/null {} +

1
मुझे नहीं लगता है कि यह काम करेगा क्योंकि नासुबर अन्य निर्देशिकाओं में main.cpp चाहता है
एरिक

1
क्या आपका पैटर्न अन्य सभी निर्देशिकाओं से main.cpp को बाहर नहीं करेगा? यह वांछनीय नहीं होगा
एरिक रेनॉफ

@ EricRenouf: ओह, मेरी गलती, एक गलत-पढ़ने। मेरे उत्तर को अपडेट किया।
cuonglm

@ गिल्स: -pathपोसिक्स क्यों नहीं है?
cuonglm

आह, क्षमा करें, मेरी गलती है, यह 2008 में जोड़ा गया है। फिर भी सोलारिस से गायब है।
गाइल्स का SO- बुराई होना बंद हो गया '21

1

रिकॉर्ड के लिए, यहां वह तरीका है जो मुझे पसंद है:

grep pattern $(find . -type f ! -path './test/main.cpp')

grepकमांड की शुरुआत में रखने से , मुझे लगता है कि यह थोड़ा और स्पष्ट है - साथ ही यह grepरंग हाइलाइटिंग को अक्षम नहीं करता है । एक अर्थ में, findकमांड-प्रतिस्थापन में उपयोग करना (सीमित) फाइल-सर्च सब्मिट की जगह को बढ़ाने / बदलने का एक तरीका है grep


मेरे लिए, find -execवाक्यविन्यास एक प्रकार का पुरालेख है। find -exec(कभी-कभी) विभिन्न पात्रों से बचने के लिए (कभी-कभी यदि \;बैश के तहत उपयोग किया जाता है ) एक जटिलता की आवश्यकता होती है। बस चीजों को परिचित संदर्भों में रखने के प्रयोजनों के लिए, निम्नलिखित दो आदेश मूल रूप से समतुल्य हैं:

find . ! -path ./test/main.cpp -type f -exec grep pattern {} +
find . ! -path ./test/main.cpp -type f -print0 |xargs -0 grep pattern

यदि आप उपनिर्देशिका को बाहर करना चाहते हैं , तो वाइल्डकार्ड का उपयोग करना आवश्यक हो सकता है। मैं यहां स्कीमा को पूरी तरह से नहीं समझता - आर्कन के बारे में बात करता हूं :

grep pattern $(find . -type f ! -path './test/main.cpp' ! -path './lib/*' )

स्क्रिप्ट्स में उपयोग के लिए सामान्यीकृत findसमाधान के लिए एक और ध्यान दें : grepकमांड-लाइन में -H/ --with-filenameविकल्प शामिल होना चाहिए । अन्यथा यह इस परिस्थिति में आउटपुट स्वरूपण को बदल देगा कि खोज परिणामों में केवल एक फ़ाइल नाम होता है find। यह उल्लेखनीय है क्योंकि यह grepदेशी फ़ाइल-खोज ( -rविकल्प के साथ ) का उपयोग करने के लिए आवश्यक प्रतीत नहीं होता है ।

... इससे भी बेहतर, हालांकि, /dev/nullखोज के लिए पहली फ़ाइल के रूप में शामिल है । यह दो समस्याओं को हल करता है:

  • यह सुनिश्चित करता है कि अगर खोज करने के लिए एक फ़ाइल है, grepतो सोचेंगे कि दो हैं और कई-फाइल आउटपुट मोड का उपयोग करें।
  • यह सुनिश्चित करता है कि अगर खोज करने के लिए कोई फाइल नहीं है, grepतो सोचेंगे कि एक फाइल है और स्टड पर लटका नहीं है।

तो अंतिम उत्तर है:

grep pattern /dev/null $(find . -type f ! -path './test/main.cpp')

आपको findकमांड प्रतिस्थापन में आउटपुट का उपयोग नहीं करना चाहिए । यदि स्पेस या अन्य विशेष वर्णों वाले फ़ाइल नाम हैं तो यह टूट जाता है। उपयोग करें find -exec, यह मजबूत और उपयोग में आसान है।
गाइल्स का SO- बुराई पर रोक '21

@ गिल्स: बहुत अच्छा बिंदु - आउटपुट भी संभवतः कुछ कार्यक्रमों के कमांड-लाइन आकार की सीमा को पार कर सकता है। कैवियट खाली करनेवाला।
नोबार

ओह। 'खोज' वाक्यविन्यास बहुत मुश्किल है। '-o' एक "या" ऑपरेटर (लिनक्स पर भी '-or') है, लेकिन यह विशिष्ट उपयोग (उदाहरण के लिए '-prune' के साथ) तार्किक या तार्किक की धारणा के अनुरूप नहीं है। यह एक कार्यात्मक है या तार्किक या के बजाय।
18

एक नाम मिलान के आधार पर उपनिर्देशिकाओं को बाहर करने का दूसरा तरीका find -iname "*target*" -or -name 'exclude' -prune:। खैर, यह काम करता है - छंटनी निर्देशिका को सूचीबद्ध किया जाएगा, लेकिन खोजा नहीं गया। यदि आप इसे सूचीबद्ध नहीं करना चाहते हैं, तो आप एक प्रकार के निरर्थक! -name 'exclude'
nobar
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.