निर्देशिका में गैर-पुनरावर्ती सभी फ़ाइलों पर grep का उपयोग कैसे करें?


34

मैं एक निर्देशिका में सभी फ़ाइलों में पाठ की एक स्ट्रिंग की खोज करना चाहता हूं (और इसके उपनिर्देशिका नहीं; मुझे पता है कि -rविकल्प ऐसा करता है, लेकिन यह वह नहीं है जो मैं चाहता हूं)।

  1. चल रहा है

    grep "string" /path/to/dir
    

    ऐसा करने में सक्षम होना चाहिए, मैंने पढ़ा है, लेकिन यह मुझे त्रुटि देता है:

    grep: dir: एक निर्देशिका है

  2. अगला, मैंने grepकई फाइलों पर चलने की कोशिश की ।

    grep "string" .bashrc .bash_aliases अच्छी तरह से काम।

    grep "string" .bash* इरादा के अनुसार भी काम करता है।

    grep "string" * मुझे त्रुटियाँ देता है:

    grep: data: Is a directory
    grep: Desktop: Is a directory
    grep: Documents: Is a directory
    grep: Downloads: Is a directory
    ...
    

केवल त्रुटियों को मुद्रित किया जाता है, मुझे मिलान लाइनें नहीं मिलती हैं। मैंने -sविकल्प का उपयोग करने की कोशिश की , लेकिन कोई फायदा नहीं हुआ।

तो, मेरे सवाल:

  1. grepजब मैं सक्षम होना चाहिए, तो मैं (1) के रूप में एक निर्देशिका पर उपयोग करने में सक्षम क्यों नहीं हूं? मैंने देखा है कि इंटरनेट पर बहुत सारे उदाहरण हैं।
    संपादित करें : जब मैं कहता हूं "एक निर्देशिका पर grep का उपयोग कर रहा है", मेरा मतलब है "उस निर्देशिका में सभी फ़ाइलों में खोज उसके उपनिर्देशिका को छोड़कर"। मेरा मानना ​​है कि जब आप किसी निर्देशिका को किसी फ़ाइल के स्थान पर पास करते हैं तो यह grep करता है। क्या मैं गलत हूँ?

  2. कृपया मुझे उस के कामकाज पर एक स्पष्टीकरण दें, grepजो (2) में आदेशों के व्यवहार की व्याख्या करेगा।
    संपादित करें : मुझे और अधिक विशिष्ट होने दें। वाइल्डकार्ड्स का उपयोग कई फाइलों को निर्दिष्ट करने के लिए काम करने के लिए या इसके .bash*साथ *भी नहीं करने के लिए क्यों करता है ./*?

  3. मैं एक निर्देशिका में सभी फ़ाइलों को कैसे खोज सकता हूं (और इसके उपनिर्देशिका नहीं) का उपयोग कर grep?


इसके अलावा आप शेल जैसे वाइल्डकार्ड के विस्तार पर भरोसा कर रहे हैं *, जिन्हें ग्लोबिंग के रूप में जाना जाता है। ग्लोबिंग .bashrcमें मानक जैसे डॉट के साथ शुरू होने वाले फ़ाइल नाम शामिल नहीं हैं । आप शेल विकल्प सेट कर सकते हैं ताकि इसमें ये फाइलें शामिल हों, लेकिन यदि आप नहीं जानते कि आप क्या कर रहे हैं, तो आप अपने आप को थोड़ा गड़बड़ कर सकते हैं। ग्लोबिंग को समझने के लिए एक अच्छा मार्गदर्शक यहां पाया जा सकता है mywiki.wooledge.org/glob
Arronical

मुझे पता नहीं क्यों, लेकिन मैंने हमेशा छिपी हुई फाइलों पर ग्लोबिंग किया है, और यह हमेशा काम किया है। मैंने कोई सेटिंग या कुछ नहीं बदला है। जैसा कि मैंने बताया (2), यह grep "string" .bash*भी साथ काम करता है।
जॉन रेड

क्षमा करें, मेरा अंतिम उदाहरण गलत था। आप छिपी हुई फ़ाइलों में भी खोज सकते हैं और "एक निर्देशिका है" को दबा सकते हैं क्योंकि लिनक्स तकनीकी रूप से निर्देशिकाओं को एक अलग प्रकार की फ़ाइल के रूप में देखता है। कमांड तब होगा: grep "string" * .* 2>/dev/nullयाgrep -s "string" * .*
टेरेन्स

जवाबों:


40

बैश में, एक ग्लोब छिपी हुई फ़ाइलों में विस्तार नहीं करेगा, इसलिए यदि आप एक निर्देशिका में सभी फ़ाइलों को खोजना चाहते हैं, तो आपको छिपी हुई फ़ाइलों .*और गैर-छिपी को निर्दिष्ट करने की आवश्यकता है *

से बचने के लिए त्रुटियों, आप इस्तेमाल कर सकते हैं "यह एक निर्देशिका है" -d skip, लेकिन मेरे सिस्टम पर मैं भी कोई त्रुटि मिलती है grep: .gvfs: Permission denied तो मैं उपयोग करने का सुझाव, -sहै, जो सभी त्रुटि संदेश छुपाता है।

तो आप जिस आदेश की तलाश कर रहे हैं वह है:

grep -s "string" * .*

यदि आप किसी अन्य dir में फ़ाइलें खोज रहे हैं:

grep -s "string" /path/to/dir/{*,.*}

एक अन्य विकल्प dotglobशेल विकल्प का उपयोग करना है, जो एक ग्लोब को छिपी हुई फ़ाइलों को शामिल करेगा।

shopt -s dotglob
grep -s "string" *

एक और dir में फ़ाइलों के लिए:

grep -s "string" /path/to/dir/*

† किसी ने उल्लेख किया कि मुझे यह त्रुटि नहीं मिलनी चाहिए। वे सही हो सकते हैं - मैंने कुछ पठन किया, लेकिन खुद इसे प्रमुख या पूंछ नहीं बना सका।


क्या इसके बीच की जगह का कोई कारण है *और .*?
हाशिम

2
@ हाशिम अपने होम डाइरेक्टरी के आउटपुट echo * .*और echo *.*रन की तुलना करें और अंतर स्पष्ट होना चाहिए। अन्यथा LMK और मैं इसे समझाता हूँ।
वेजेंड्रिया

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

1
@ हाशिम मुझे यकीन नहीं है कि आप उन नतीजों पर कैसे आए, इसलिए मुझे समझाएं। सबसे पहले, निर्देशिका इस संदर्भ में फाइलें हैं। ग्लब्स में, *सभी गैर-छिपी हुई फ़ाइलों का प्रतिनिधित्व करता है (यानी फ़ाइलनाम जो डॉट से शुरू नहीं होते हैं ); .*सब छिपा फ़ाइलों का प्रतिनिधित्व करता है (यानी फ़ाइल नाम है कि है एक बिंदु के साथ शुरू करते हैं); और *.*सभी गैर-छिपी हुई फ़ाइलों का प्रतिनिधित्व करता है जिसमें एक डॉट होता है। में echo * .*, दो ग्लब्स अलग होने चाहिए क्योंकि वे अलग ग्लब्स हैं: एक गैर-छिपे हुए के लिए, एक छिपे हुए के लिए। हालांकि जैसा कि मैंने अपने उत्तर में लिखा था, आप शेल विकल्प *को चालू करके छिपी हुई फ़ाइलों को शामिल कर सकते हैं dotglob
wjandrea

1
*.*Windows (DOS) पर सभी फ़ाइलों को सूचीबद्ध करने के तरीके के रूप में उपयोग करना आम है लेकिन * nix में केवल उन में डॉट वाली फाइलें शामिल होंगी, इसलिए यह * nix पर कोई मतलब नहीं रखता है। इसके बजाय आप *छुपी हुई फ़ाइलों को छोड़कर सभी फाइलों को .*सूचीबद्ध करने के लिए और छिपी हुई फाइलों को सूचीबद्ध करने के लिए उपयोग करते हैं।
थोमसट्रेटर

10

आप -d skipपर जोड़ा विकल्प की जरूरत है ।

  1. ग्रीप फाइलों के अंदर खोज कर रहा है। आप पुनरावर्ती खोज कर सकते हैं, जैसा कि आपने कहा था, यदि आप किसी निर्देशिका के अंदर फ़ाइलों को खोजना चाहते हैं।

  2. डिफ़ॉल्ट रूप से, grep सभी फ़ाइलों को पढ़ेगा, और यह निर्देशिकाओं का पता लगाता है। क्योंकि डिफ़ॉल्ट रूप से आपने परिभाषित नहीं किया है कि -dविकल्प के साथ निर्देशिकाओं का क्या करना है , यह त्रुटि आउटपुट देता है।

  3. मूल निर्देशिका के भीतर खोज करना होगा 'grep -d स्किप "स्ट्रिंग" ./ !!!!


Grep पर अधिक जानकारी के लिए, देखें man grep
अनाम 2

(a) कृपया संपादन देखें। (बी) का उपयोग करना -d skipकाम नहीं करता है; यह मूल रूप से जैसा है -s; यह भी देखें, संपादित करें। (ग) नहीं, grep -d skip "string" ./*काम नहीं करता है।
जॉन रेड

7

पुराने टाइमर शायद ऐसा करेंगे:

find . -type f -print0 | xargs -0 grep "string"

3
क्यों नहीं find . -type f -exec grep string {} +?
वचर्जिन

5
आप भी चाहते हैं -maxdepth 1
व्रजगिन

@ शार्गिन: यदि आप आउटपुट में फ़ाइल का नाम चाहते हैं, तो केवल एक ही फाइल है जो मुझे लगता है कि आप चाहते हैंfind . -type f -maxdepth 1 -exec grep string /dev/null {} +
ग्रेगरी निस्बेट

1
@GregoryNisbet: बस -Hgrep पास करें।
वचर्जिन

2

रीफ़्रेशिंग - आप उपनिर्देशिका के एक स्तर में फ़ाइलों को पकड़ना चाहते हैं, लेकिन सभी उप-उप-निर्देशिकाओं की पुनरावृत्ति नहीं करते हैं?

grep forthis  *  */*

या यदि आप वर्तमान निर्देशिका में फाइलें नहीं चाहते हैं

grep forthis  */*

ध्यान दें कि यह डायरेक्ट्री डॉट से शुरू नहीं होगी।

grep forthis  .*/*    */*   

वह काम करना चाहिए।

वहाँ भी है -maxdepthऔर आदेश के -mindepthलिए प्रतिबंध प्रतिबंध भी उपलब्ध findहै।


grep forthis */*वर्तमान निर्देशिका और एक निर्देशिका नीचे दोनों में फ़ाइलों को नहीं खोज पाएंगे ?
हाशिम

@ हाशिम नाच ज्यादातर - cos */*केवल एक स्लैश के साथ चीजों से मेल खाता है। यदि आपके पास a/bवर्तमान निर्देशिका में एक फ़ाइल है तो `* / * का मिलान होगा।
क्रैगी

0

यहां सभी त्रुटियों को छोड़ बिना निर्देशिकाओं को छोड़ने का एक उदाहरण दिया गया है:

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