लिनक्स कमांड: केवल पाठ फ़ाइलों को 'खोजने' के लिए कैसे?


100

Google की कुछ खोजों के बाद, मैं क्या कर रहा हूँ:

find my_folder -type f -exec grep -l "needle text" {} \; -exec file {} \; | grep text

जो बहुत अस्वाभाविक है और अनइम्पेक्टेड टेक्स्ट जैसे कि माइम प्रकार की जानकारी देता है। कोई बेहतर उपाय? मेरे पास बहुत सारी टेक्स्ट फाइलें और बहुत सारी बाइनरी फाइलें हैं जिनमें बहुत सारी टेक्स्ट फाइलें हैं, जिनके माध्यम से मुझे खोज करनी है।

जवाबों:


184

मुझे पता है कि यह एक पुराना धागा है, लेकिन मैंने इसे ठोकर खाया और सोचा कि मैं अपनी विधि साझा करूँगा जिसे मैंने findकेवल गैर-बाइनरी फ़ाइलों को खोजने के लिए उपयोग करने के लिए एक बहुत तेज़ तरीका पाया है :

find . -type f -exec grep -Iq . {} \; -print

-IGrep का विकल्प इसे तुरंत बाइनरी फ़ाइलों को अनदेखा करने के लिए कहता है और वसीयत .के साथ विकल्प -qइसे तुरंत पाठ फ़ाइलों से मेल खाता है इसलिए यह बहुत तेज़ी से जाता है। आप बदल सकते हैं -printएक करने के लिए -print0एक में पाइपिंग के लिए xargs -0यदि आप रिक्त स्थान के बारे में चिंतित हैं या कुछ और (टिप के लिए धन्यवाद, @ lucas.werkmeister!)

इसके अलावा पहली बिंदी केवल कुछ बीएसडी संस्करणों findजैसे ओएस एक्स के लिए ही आवश्यक है , लेकिन यह किसी भी चीज को नुकसान नहीं पहुंचाता है यदि आप इसे किसी अन्य चीज या किसी चीज में रखना चाहते हैं।

संपादित करें : जैसा कि @ruslan ने सही ढंग से बताया है, -andगर्भित होने के बाद से इसे छोड़ा जा सकता है।


16
मैक ओएस एक्स पर, मुझे इसे बदलने की आवश्यकता है find . -type f -exec grep -Il "" {} \;
एलेक जैकबसन

3
यह peoro के उत्तर से बेहतर है क्योंकि 1. यह वास्तव में सवाल का जवाब देता है। 2. यह झूठी सकारात्मकता उत्पन्न नहीं करता है। यह अधिक प्रदर्शन करने वाला है
user123444555621

3
आप यह भी उपयोग कर सकते हैं find -type f -exec grep -Iq . {} \; -and -printकि इसमें कौन सा लाभ है जो फाइलों को रखता है find; आप -printदूसरे के साथ विकल्प चुन सकते हैं -execजो केवल पाठ फ़ाइलों के लिए चलाया जाता है। (यदि आप grepफ़ाइल नामों को प्रिंट करते हैं, तो आप फ़ाइल नामों को उन में नई सूची के साथ अंतर नहीं कर पाएंगे।)
लुकास वेर्कमेस्टर

1
@ NathanS.Watson-Haigh यह नहीं होना चाहिए, क्योंकि यह तुरंत पाठ फ़ाइलों से मेल खाना चाहिए। क्या आपके पास एक विशिष्ट उपयोग का मामला है जिसे आप साझा कर सकते हैं?
crudcore

2
find . -type f -exec grep -Il . {} +बहुत तेज है। -execदोष यह है कि इसे @ lucas.werkmeister के रूप में एक और द्वारा बढ़ाया नहीं जा सकता है
हेनिंग


10

यह अनहोनी क्यों है? यदि आपको इसे अक्सर उपयोग करने की आवश्यकता है, और हर बार इसे टाइप करना नहीं चाहते हैं तो बस इसके लिए एक बश फ़ंक्शन परिभाषित करें:

function findTextInAsciiFiles {
    # usage: findTextInAsciiFiles DIRECTORY NEEDLE_TEXT
    find "$1" -type f -exec grep -l "$2" {} \; -exec file {} \; | grep text
}

इसे अपने अंदर रखो .bashrcऔर फिर दौड़ो:

findTextInAsciiFiles your_folder "needle text"

जब भी आप चाहते हैं।


EDIT को ओपी के संपादन को प्रतिबिंबित करने के लिए:

यदि आप माइम informations को काटना चाहते हैं, तो आप पाइपलाइन में एक और चरण जोड़ सकते हैं जो माइम informations को फ़िल्टर करता है। यह चाल करना चाहिए केवल लेने से पहले क्या आता है द्वारा :: cut -d':' -f1:

function findTextInAsciiFiles {
    # usage: findTextInAsciiFiles DIRECTORY NEEDLE_TEXT
    find "$1" -type f -exec grep -l "$2" {} \; -exec file {} \; | grep text | cut -d ':' -f1
}

मुझे यकीन नहीं है कि क्या "grep text" बिल्कुल सटीक है सभी टेक्स्ट फ़ाइलों को प्राप्त करने के लिए - मेरा मतलब है कि क्या कोई टेक्स्ट फ़ाइल प्रकार है, जिसके माइम प्रकार के विवरण की स्ट्रिंग में कोई 'टेक्स्ट' नहीं है?
datasn.io

@ kavoir.com: हाँ। से fileमैनुअल: "उपयोगकर्ता जानते हुए भी कि एक निर्देशिका में सभी पठनीय फ़ाइलों शब्द 'पाठ' मुद्रित है पर निर्भर करते हैं।"
पीरो

2
क्या ग्रेपिंग से पहले ग्रिपिंग के बजाय टेक्स्ट फ़ाइलों की खोज करना और पाठ फ़ाइलों को फ़िल्टर करना थोड़ा अधिक चतुर नहीं होगा?
उपयोगकर्ता अज्ञात

/proc/meminfo, /proc/cpuinfoआदि पाठ फ़ाइलें हैं, लेकिन file /proc/meminfoकहते हैं /proc/meminfo: empty। मुझे आश्चर्य है कि यदि 'पाठ' के अलावा 'खाली' का परीक्षण किया जाना चाहिए, लेकिन यह सुनिश्चित नहीं है कि क्या अन्य प्रकार भी 'खाली' की रिपोर्ट कर सकते हैं।
टिमो किक्कोन ने

"यह अनहोनी क्यों है?" - "अनावश्यक ग्रंथों को आउटपुट करता है"। यह उत्तर ऐसा नहीं है।
user123444555621

4
find . -type f -print0 | xargs -0 file | grep -P text | cut -d: -f1 | xargs grep -Pil "search"

यह दुर्भाग्य से अंतरिक्ष की बचत नहीं है। इसे बैश स्क्रिप्ट में डालने से यह थोड़ा आसान हो जाता है।

यह स्थान सुरक्षित है:

#!/bin/bash
#if [ ! "$1" ] ; then
    echo "Usage: $0 <search>";
    exit
fi

find . -type f -print0 \
  | xargs -0 file \
  | grep -P text \
  | cut -d: -f1 \
  | xargs -i% grep -Pil "$1" "%"

2
आपकी स्क्रिप्ट में कुछ मुद्दे हैं: 1. क्या होगा यदि एक बाइनरी फ़ाइल का नाम है text.bin? 2. क्या होगा यदि फ़ाइल नाम में ए हो :?
थकाला

3

इसे करने का दूसरा तरीका:

# find . |xargs file {} \; |grep "ASCII text"

यदि आप खाली फाइलें भी चाहते हैं:

#  find . |xargs file {} \; |egrep "ASCII text|empty"

2

इस बारे में कैसा है:

$ grep -rl "needle text" my_folder | tr '\n' '\0' | xargs -r -0 file | grep -e ':[^:]*text[^:]*$' | grep -v -e 'executable'

यदि आप फ़ाइल प्रकार के बिना फ़ाइल नाम चाहते हैं, तो बस एक अंतिम sedफ़िल्टर जोड़ें ।

$ grep -rl "needle text" my_folder | tr '\n' '\0' | xargs -r -0 file | grep -e ':[^:]*text[^:]*$' | grep -v -e 'executable' | sed 's|:[^:]*$||'

आप -e 'type'अंतिम grepआदेश में अधिक विकल्प जोड़कर अनावश्यक फ़ाइल प्रकारों को फ़िल्टर कर सकते हैं ।

संपादित करें:

यदि आपका xargsसंस्करण -dविकल्प का समर्थन करता है, तो ऊपर दिए गए आदेश सरल हो जाते हैं:

$ grep -rl "needle text" my_folder | xargs -d '\n' -r file | grep -e ':[^:]*text[^:]*$' | grep -v -e 'executable' | sed 's|:[^:]*$||'

मुझे मूर्ख। पुनरावर्ती grep नोटिस नहीं किया। जैसा कि मैंने समझा कि यह वास्तव में बहुत तेज़ है, भले ही कई अनुप्रयोगों में थोड़ा सीमित है। आपके लिए +1।
अंती रत्सला

2

यहाँ मैंने इसे कैसे किया है ...

१। यदि कोई फ़ाइल सादा पाठ istext है तो परीक्षण करने के लिए एक छोटी सी स्क्रिप्ट बनाएं:

#!/bin/bash
[[ "$(file -bi $1)" == *"file"* ]]

२। पहले की तरह उपयोग करें

find . -type f -exec istext {} \; -exec grep -nHi mystring {} \;

मुझे लगता है कि तुम मतलब है == *"text"* ]]?
उपयोगकर्ता अज्ञात

आप इसके बजाय मैच-संचालक `= ~" पाठ "]] का उपयोग कर सकते हैं।
उपयोगकर्ता अज्ञात

2

मेरे पास इतिहास के उत्तर के साथ दो मुद्दे हैं:

  • यह केवल पाठ फ़ाइलों को सूचीबद्ध करता है। यह वास्तव में उन्हें अनुरोध के अनुसार नहीं खोजता है। वास्तव में खोज करने के लिए, का उपयोग करें

    find . -type f -exec grep -Iq . {} \; -and -print0 | xargs -0 grep "needle text"
    
  • यह हर फ़ाइल के लिए एक grep प्रक्रिया को जन्म देता है, जो बहुत धीमी है। एक बेहतर समाधान तो है

    find . -type f -print0 | xargs -0 grep -IZl . | xargs -0 grep "needle text"
    

    या केवल

    find . -type f -print0 | xargs -0 grep -I "needle text"
    

    यह केवल ऊपर समाधान (2.5GB डेटा / 7700 फ़ाइलों) के लिए 4s की तुलना में 0.2s लेता है, यानी 20x तेज़ी से

इसके अलावा, किसी ने भी एजी, सिल्वर सर्चर या एकेक -जीआरपी विकल्प का हवाला नहीं दिया । यदि इनमें से एक उपलब्ध है, तो वे बेहतर विकल्प हैं:

ag -t "needle text"    # Much faster than ack
ack -t "needle text"   # or ack-grep

अंतिम नोट के रूप में, झूठी सकारात्मकता से सावधान रहें (पाठ फ़ाइलों के रूप में ली गई बाइनरी फाइलें)। मेरे पास पहले से ही grep / ag / ack का उपयोग करके गलत सकारात्मक था, इसलिए फ़ाइलों को संपादित करने से पहले पहले मिलान की गई फ़ाइलों को बेहतर सूची दें।


1

हालाँकि यह एक पुराना सवाल है, मुझे लगता है कि यह जानकारी यहाँ जवाबों की गुणवत्ता को बढ़ाएगी।

निष्पादन योग्य बिट सेट के साथ फ़ाइलों को अनदेखा करते समय , मैं बस इस कमांड का उपयोग करता हूं:

find . ! -perm -111

इसे अन्य निर्देशिकाओं में पुनरावृत्ति से रखने के लिए:

find . -maxdepth 1 ! -perm -111

के लिए कोई ज़रूरत नहीं पाइप आदेशों के बहुत सारे, बस शक्तिशाली सादा मिश्रण खोजने के आदेश।

  • डिस्क्लेमर: यह बिल्कुल वैसा नहीं है जैसा ओपी ने पूछा है, क्योंकि यह जांच नहीं करता है कि फाइल बाइनरी है या नहीं। उदाहरण के लिए, यह बैश स्क्रिप्ट फ़ाइलों को फ़िल्टर करेगा, जो स्वयं पाठ हैं लेकिन निष्पादन योग्य बिट सेट हैं

मैंने कहा, मुझे उम्मीद है कि यह किसी के लिए भी उपयोगी है।


0

मैं इसे इस तरह से करता हूं: 1) क्योंकि थ्रू को खोजने के लिए बहुत सारी फाइलें (~ 30k) हैं, मैं नीचे दिए गए कमांड का उपयोग करके crontab के माध्यम से उपयोग के लिए दैनिक पाठ सूची बनाता हूं:

find /to/src/folder -type f -exec file {} \; | grep text | cut -d: -f1 > ~/.src_list &

2) .bashrc में एक फंक्शन बनाएं:

findex() {
    cat ~/.src_list | xargs grep "$*" 2>/dev/null
}

फिर मैं खोज करने के लिए नीचे दिए गए आदेश का उपयोग कर सकता हूं:

findex "needle text"

HTH :)


0

मुझे xargs पसंद है

find . -type f | xargs grep -I "needle text"

यदि आपके फ़ाइल नाम अजीब हैं, तो -0 विकल्पों का उपयोग करें:

find . -type f -print0 | xargs -0 grep -I "needle text"

0
  • सभी पाठ / ascii फ़ाइलों में / आदि में पाठ "eth0" को प्रसारित करने के लिए bash उदाहरण

grep eth0 $ (ढूँढें / etc / -Type fexec file {} \;? egrep -i "text | ascii" | cut -d ':' -f1)


0

यहां मेरे जैसे शुरुआती लोगों के लिए विस्तारित स्पष्टीकरण के साथ एक सरलीकृत संस्करण है जो सीखने की कोशिश कर रहे हैं कि एक पंक्ति में एक से अधिक कमांड कैसे डाल सकते हैं।

यदि आप समस्या को चरणों में लिखना चाहते हैं, तो यह इस तरह दिखेगा:

// For every file in this directory
// Check the filetype
// If it's an ASCII file, then print out the filename

इस लक्ष्य को हासिल करने के लिए, हम तीन यूनिक्स आदेशों का उपयोग कर सकते हैं: find, file, और grep

find निर्देशिका में हर फ़ाइल की जाँच करेगा।

fileहमें फिलामेंट देगा। हमारे मामले में, हम 'ASCII पाठ' की वापसी की तलाश कर रहे हैं

grep से आउटपुट में 'ASCII' कीवर्ड खोजेंगे file

तो हम कैसे एक साथ एक पंक्ति में इन स्ट्रिंग कर सकते हैं? इसे करने के कई तरीके हैं, लेकिन मुझे लगता है कि हमारे छद्म कोड के क्रम में ऐसा करना सबसे अधिक समझ में आता है (विशेषकर मेरे जैसे शुरुआती के लिए)।

find ./ -exec file {} ";" | grep 'ASCII'

जटिल लगता है, लेकिन बुरा नहीं जब हम इसे तोड़ देते हैं:

find ./= इस निर्देशिका की प्रत्येक फ़ाइल को देखें। findकि 'अभिव्यक्ति' से मेल खाता है, या जो कुछ भी किसी भी फ़ाइल का फ़ाइल नाम बाहर आदेश प्रिंट पथ, जो हमारे मामले में वर्तमान निर्देशिका है या के बाद आता है./

समझने के लिए सबसे महत्वपूर्ण बात यह है कि पहले बिट के बाद का सब कुछ सच या गलत के रूप में मूल्यांकन किया जाएगा। यदि सही है, तो फ़ाइल का नाम प्रिंट आउट हो जाएगा। यदि नहीं, तो कमांड चलता रहता है।

-exec= यह ध्वज खोज कमांड के भीतर एक विकल्प है जो हमें खोज अभिव्यक्ति के रूप में कुछ अन्य कमांड के परिणाम का उपयोग करने की अनुमति देता है। यह एक फ़ंक्शन के भीतर एक फ़ंक्शन को कॉल करने जैसा है।

file {}= अंदर बुलाया जा रहा है findfileआदेश एक स्ट्रिंग है कि आप एक फ़ाइल के फ़ाइल प्रकार बताता है देता है। नियमित रूप से, यह इस तरह दिखेगा file mytextfile.txt:। हमारे मामले में, हम चाहते हैं कि findकमांड द्वारा जो भी फ़ाइल देखी जा रही है, उसका उपयोग करें , इसलिए हम {}एक खाली चर या पैरामीटर के रूप में कार्य करने के लिए घुंघराले ब्रेसिज़ में डालते हैं । दूसरे शब्दों में, हम सिस्टम से निर्देशिका में हर फ़ाइल के लिए एक स्ट्रिंग आउटपुट करने के लिए कह रहे हैं।

";"= इसके लिए आवश्यक है findऔर हमारी -execकमांड के अंत में विराम चिह्न है । यदि आपको इसे चलाने की आवश्यकता है, तो अधिक विवरण के लिए 'खोज' के लिए मैनुअल देखें man find

| grep 'ASCII'= |एक पाइप है। पाइप बाईं ओर जो कुछ भी है उसका आउटपुट लेता है और जो कुछ भी दाईं ओर है उसका इनपुट के रूप में उपयोग करता है। यह findकमांड का आउटपुट लेता है (एक स्ट्रिंग जो कि किसी एकल फ़ाइल का फ़ाइल टाइप है) और यह देखने के लिए परीक्षण करता है कि इसमें स्ट्रिंग है या नहीं 'ASCII'। यदि ऐसा होता है, तो यह सच है।

find ./जब grepआदेश सही वापस आता है, तो सही के एक्सप्रेशन सही आएंगे । देखा।


0

यदि आप किसी भी प्रकार की फ़ाइल को उनके मैजिक बाइट्स द्वारा खोजने में रुचि रखते हैं , तो इसकी fileशक्ति के साथ संयुक्त भयानक उपयोगिता का उपयोग करके find, यह काम आ सकता है:

$ # Let's make some test files
$ mkdir ASCII-finder
$ cd ASCII-finder
$ dd if=/dev/urandom of=binary.file bs=1M count=1
1+0 records in
1+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.009023 s, 116 MB/s
$ file binary.file
binary.file: data
$ echo 123 > text.txt
$ # Let the magic begin
$ find -type f -print0 | \
    xargs -0 -I @@ bash -c 'file "$@" | grep ASCII &>/dev/null && echo "file is ASCII: $@"' -- @@

आउटपुट:

file is ASCII: ./text.txt

किंवदंती: $इंटरएक्टिव शेल प्रॉम्प्ट है जहां हम अपनी कमांड दर्ज करते हैं

आप &&किसी अन्य स्क्रिप्ट को कॉल करने के बाद भाग को संशोधित कर सकते हैं या कुछ अन्य सामान इनलाइन भी कर सकते हैं, अर्थात यदि उस फ़ाइल में दिए गए स्ट्रिंग हैं, तो पूरी फ़ाइल को कैट करें या उसमें द्वितीयक स्ट्रिंग की तलाश करें।

स्पष्टीकरण:

  • find आइटम जो फ़ाइलें हैं
  • xargsएक लाइनर bash कमांड / स्क्रिप्ट में एक लाइन के रूप में प्रत्येक आइटम को फ़ीड करें
  • fileमैजिक बाइट द्वारा फ़ाइल के प्रकार की grepजाँच करता है, अगर ASCII मौजूद है, तो यदि &&आपका अगला कमांड निष्पादित होता है , तो जाँच करता है।
  • findप्रिंट परिणाम nullअलग हो गए, इसमें रिक्त स्थान और मेटा-पात्रों के साथ फ़ाइल नाम से बचना अच्छा है।
  • xargs, -0विकल्प का उपयोग करते हुए , उन्हें nullअलग-अलग पढ़ता है , -I @@ प्रत्येक रिकॉर्ड लेता है और स्क्रिप्ट को कोसने के लिए स्थितीय पैरामीटर / आर्ग के रूप में उपयोग करता है।
  • --के लिए bashसुनिश्चित जो कुछ होने के बाद यह एक तर्क है की बात आती है तो भी यह साथ शुरू होता है -की तरह -cहै जो अन्यथा बैश विकल्प के रूप में व्याख्या की जा सकती

यदि आपको ASCII के अलावा अन्य प्रकार खोजने की आवश्यकता है, तो बस grep ASCIIअन्य प्रकार की जगह लें , जैसेgrep "PDF document, version 1.4"


-1
find . -type f | xargs file | grep "ASCII text" | awk -F: '{print $1}'

सभी फ़ाइलों को सूचीबद्ध करने के लिए कमांड का उपयोग करें, पाठ (टार नहीं, कुंजी) को सत्यापित करने के लिए फ़ाइल कमांड का उपयोग करें, अंत में परिणाम को फ़िल्टर और प्रिंट करने के लिए awk कमांड का उपयोग करें।


-4

इस बारे में कैसा है

 find . -type f|xargs grep "needle text"

इस के लिए नहीं लग रही है"needle text"
peoro

@ नई: ओपी ने जो उदाहरण दिया है, उसमें केवल फाइलें ही हैं"needl text"
peoro

3
@ नई: अब यह पाठ फ़ाइलों की तलाश नहीं करता है: यदि किसी बाइनरी फ़ाइल में "needle text"यह पाया जाएगा
peoro

मैं भी आपकी बात क्यों सुन रहा हूँ?
नवी

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