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


11

मैं खुद को शूट करने में कामयाब रहा, जहां मूल्यवान डेटा रखने वाले विभाजन को सुधारने से यह (वास्तव में बुरा) दर्द होता है। बेशक यह जानबूझकर नहीं था, लेकिन ऐसा हुआ।

हालांकि, मैं अधिकांश डेटा का उपयोग करने testdiskऔर photorecपुनर्प्राप्त करने में कामयाब रहा । तो अब मेरे पास लगभग 25,000 निर्देशिकाओं को वितरित किया गया डेटा है। अधिकांश फाइलें .txt फाइलें हैं, जबकि बाकी इमेज फाइलें हैं। प्रत्येक निर्देशिका में 300 से अधिक .txt फाइलें हैं।

मैं .txt फ़ाइलों से कुछ तार निकालने और उन्हें एक फ़ाइल में आउटपुट करने के लिए grepउपयोग या उपयोग कर सकता हूं find। उदाहरण के लिए, यहां एक पंक्ति है जिसका उपयोग मैंने यह सत्यापित करने के लिए किया है कि मेरा डेटा पुनर्प्राप्त फ़ाइलों में है:

find ./recup*/ -name '*.txt' -print | xargs grep -i "searchPattern"

मैं एक फ़ाइल के लिए "searchPattern" आउटपुट कर सकता हूं, लेकिन यह सिर्फ मुझे वह पैटर्न देता है। यहाँ मैं वास्तव में क्या हासिल करना चाहूंगा:

सभी फ़ाइलों के माध्यम से जाओ और एक विशिष्ट स्ट्रिंग की तलाश करें। यदि वह स्ट्रिंग किसी फ़ाइल में मिलती है, तो उस फ़ाइल की सभी सामग्री को आउटपुट फ़ाइल में कैट करें। यदि पैटर्न एक से अधिक फ़ाइल में पाया जाता है, तो उस आउटपुट फ़ाइल में बाद की फ़ाइलों की सामग्री को जोड़ दें। ध्यान दें कि मैं सिर्फ उस पैटर्न को आउटपुट नहीं करना चाहता जिसे मैं खोज रहा हूं, लेकिन फ़ाइल की सभी सामग्री जिसमें पैटर्न पाया जाता है।

मुझे लगता है कि यह उल्लेखनीय है, लेकिन मुझे अभी यह नहीं पता है कि किसी विशिष्ट पैटर्न को टटोलने के बाद किसी फ़ाइल की सभी सामग्री को कैसे पकड़ा जाए।


तो आपके द्वारा प्रदान की गई कमांड के साथ, यह आपको वह परिणाम देता है जिसकी आप तलाश कर रहे हैं, लेकिन आप आउटपुट को टेक्स्ट फ़ाइल में रीडायरेक्ट करना चाहते हैं?
रेकायो

मेरे प्रश्न को पढ़ने के बाद, वह पैराग्राफ जो "गो थ्रू ..." से शुरू होता है, बस पसियोकोडो की तरह लगता है। शायद मैं इसे कुछ पंक्तियों के साथ / यदि पायथन कोड के साथ कोड प्राप्त कर सकता हूं। जब मैं एक अधिक सूचित प्रतिक्रिया का इंतजार कर रहा हूं, तो इसे एक शॉट दूंगा
एमी

यह निश्चित रूप से psuedocode है, और Im यकीन है कि आप इसे बैश में भी कर सकते हैं।
रेकायो

@ryekayo, हाँ, यह मुझे आउटपुट देता है, लेकिन यह केवल यह पता लगाना है कि एक विशिष्ट प्रकार का डेटा किस फ़ाइल में है, जो मुझे बताता है कि उस फ़ाइल में अधिक डेटा है। इसलिए मैं उस फाइल में सब कुछ हड़पना चाहता हूं और उन्हें दूसरी फाइल पर लिखना चाहता हूं।
अमी

आप शायद उस आदेश को किसी प्रकार के बयान या किसी स्विच-केस में भी लपेट सकते हैं, जो किसी फ़ंक्शन को कॉल कर सकता है जो कि केस या परिणाम के आधार पर सामग्री को पूरा कर सकता है
ryekayo

जवाबों:


10

अगर मैं आपके लक्ष्य को सही ढंग से समझ पाऊं, तो निम्नलिखित आपको वही करना होगा जो आप चाहते हैं:

find ./recup*/ -name '*.txt' -exec grep -qi "searchPattern" {} \; -exec cat {} \; > outputfile.txt

यह सभी *.txtफ़ाइलों की खोज करेगा , यदि यह फ़ाइल से मेल खाता है, तो ./recup*/प्रत्येक के लिए परीक्षण करें । सभी एड फाइलों के आउटपुट को निर्देशित किया जाएगा ।searchPatterncatcatoutputfile.txt

प्रत्येक पैटर्न और आउटपुट फ़ाइल के लिए दोहराएं।


यदि आपके पास बहुत बड़ी संख्या में निर्देशिकाएं हैं ./recup*, तो आप एक के साथ समाप्त हो सकते हैं argument list too long error। इसके आसपास का सरल तरीका यह है कि इसके बजाय कुछ इस तरह किया जाए:

find ./ -mindepth 2 -path './recup*.txt' -exec grep -qi "searchPattern" {} \; -exec cat {} \; > outputfile.txt

यह पूर्ण पथ से मेल खाएगा। तो ./recup01234/foo/bar.txtमिलान किया जाएगा। यह -mindepth 2इतना है कि यह मेल नहीं खाएगा ./recup.txt, या ./recup0.txt


हां, मुझे लगता है कि यह कर देगा। और यह मुझे काम करने के लिए एक आधार देता है। चूंकि मैं कई स्ट्रिंग्स की खोज करने जा रहा हूं, इसलिए मुझे लगता है कि / के लिए यदि कोई कोड है, तो कई एलिफ की मदद से मुझे कार्य को स्वचालित करने में मदद मिलेगी। धन्यवाद
अमी

इससे भी बेहतर मैं क्या सोच रहा था lol
ryekayo

यह काम नहीं लगता था। इस त्रुटि को मिला: "निष्पादित / usr / बिन / खोजने में असमर्थ: तर्क सूची बहुत लंबी है"
अमी

@Ami ने उस मुद्दे का समाधान प्रदान करने के लिए अद्यतन उत्तर दिया।
पैट्रिक

2
@Ami यदि आप कई स्ट्रिंग्स का उपयोग कर रहे हैं, तो सभी पॉज़िटिव फ़ाइल नामों को किसी अन्य फ़ाइल ( grep -l), |sort|uniqऔर फिर catफ़ाइल सूची से सहेजना सरल हो सकता है ।
स्पार्हॉक

3

अपने पैटर्न को आउटपुट करने के बजाय, grep पर "-l" का उपयोग करके फाइलनेम को आउटपुट करें, और फिर कैट के इनपुट के रूप में इसका उपयोग करें।

find ./recup*/ -name '*.txt' -print | xargs grep -li "searchPattern" | xargs cat

या

cat $( find ./recup*/ -name '*.txt' -print | xargs grep -li "searchPattern")

मुझे संदेह है कि आप शेष विवरण भर सकते हैं। BTW, यदि आपके पास फ़ाइल नाम में रिक्त स्थान या अन्य विषम वर्ण हो सकते हैं (इस विशिष्ट मामले में, लेकिन भविष्य के उद्देश्यों के लिए), खोज पर -print0 का उपयोग करें और grep पर -Z, xargs पर -0 विकल्प के साथ संयुक्त का उपयोग करें नई कहानियों के बजाय फ़ाइलनामों के बीच अशक्त बाइट्स।

find ./recup*/ -name '*.txt' -print0 | xargs -0 grep -Zli "searchPattern" | xargs -0 cat

2
मुझे पैट्रिक का "टू-नेट" विकल्प भी पसंद है, सिवाय इसके कि यह एक नया कांटा (अच्छी तरह से, क्लोन) (और) और हर फ़ाइल के लिए निष्पादित करेगा। आम तौर पर आप उस समस्या से बचने के \+बजाय उपयोग कर सकते हैं \;, लेकिन मुझे नहीं पता कि यह कैसे एक जोड़ी के साथ काम करता है -exec args (मुझे "खराब" संदेह है)। Xargs की एक जोड़ी का उपयोग करते हुए, आप केवल कुछ नई प्रक्रियाएँ करने जा रहे हैं, जो बहुत सारी फ़ाइलों के साथ तेज़ होनी चाहिए।
dannysauer

यह अच्छा भी लग रहा है। धन्यवाद। एक noob सवाल: अंतिम xargs के बाद बिल्ली एक फ़ाइल के लिए outputting होना चाहिए, है ना?
अमी

जब मैंने पहली बार इसे पढ़ा, तो मुझे नहीं लगा कि यह प्रश्न निर्दिष्ट है कि फ़ाइल की सामग्री कहाँ जानी चाहिए। इन तीनों कमांडों ने फ़ाइल को एसटीडीयूएस पर डाला, इसलिए आप सिर्फ (बहुत अंत तक) >afileया |acommandआपकी स्थिति के लिए उपयुक्त होंगे। :)
dannysauer

अच्छा जवाब, मुझे बिल्ली की जरूरत है pg_hba.conf sudo find /* -name pg_hba.conf | xargs sudo cat
ऐप वर्क

यह थोड़ा ऑफ-टॉपिक है, लेकिन मैं sudo xargsइसके बजाय का उपयोग करना पसंद करता हूं xargs sudo। जब आप चलते हैं xargs sudo, तो यह कमांड लाइन बनाता है जो यह मानती है कि कमांड है sudo cat args। लेकिन बिल्ली / बिन में है, तो सूडो चलाता है /bin/cat args। यदि आपकी कमांड एक लंबी निर्देशिका में है, जैसे / usr / लोकल / बिन, तो कमांड sudo वास्तव में बहुत लंबी कमांड लाइन में परिणामित हो सकता है और एक त्रुटि जो नीचे ट्रैक करना मुश्किल है। उसके शीर्ष पर, sudo xargsबस लॉग जो आपने xargs चलाया था, जबकि xargs sudoसभी तर्कों के साथ कमांड को लॉग करता है - जिसके परिणामस्वरूप कुछ लंबी सुडौल लॉग लाइनें होती हैं। :)
डेनिसॉयर

1

यह बिल्कुल इष्टतम कोड नहीं है, लेकिन यह बहुत सीधा है और अगर दक्षता कोई समस्या नहीं है तो यह ठीक काम करेगा। समस्या यह है कि यह कई बार फाइलों के माध्यम से पकड़ लेगा, भले ही उनमें पहले से ही स्ट्रिंग पाया गया हो।

सबसे पहले, अपने स्ट्रिंग्स की खोज करें और मिलान फ़ाइलों को एक सूची में लिखें।

find ./recup*/ -name '*.txt' -execdir grep -il "searchPattern" {} >> /tmp/file_list \;

searchPatternआवश्यक के रूप में इस चरण को दोहराएं । यह मेल खाने वाली फाइलों की सूची तैयार करता है /tmp/file_list

समस्या यह है कि इस फ़ाइल में डुप्लिकेट हो सकता है। इसलिए, हम डुप्लिकेट को बदल सकते हैं |sort|uniqsortभाग डुप्लिकेट एक दूसरे के निकट रखता है, ताकि uniqउन्हें निकाल सकते हैं। फिर आप catइन फ़ाइलों को एक साथ xargs(newline द्वारा अलग किए गए प्रत्येक फ़ाइल नाम के साथ) का उपयोग कर सकते हैं \n। इसलिये,

</tmp/file_list sort | uniq | xargs -d "\n" cat > final_file.txt

अन्य उत्तरों के विपरीत, इसमें दो चरण हैं, और एक अस्थायी फ़ाइल है, इसलिए मैं वास्तव में केवल इसे सुझाऊंगा यदि आपके पास खोजने के लिए कई पैटर्न हैं।


0

आपके शेल और वातावरण के आधार पर, आप ऐसा कुछ कर सकते हैं (बैश में)

while IFS= read -r -d '' file; do
  if grep -qim1 'searchPattern1\|searchPattern2\|searchPattern3' "$file"; then
    cat "$file" >> some/other/file
  fi
done < <(find ./recup*/ -name '*.txt' -print0)

यदि आप पैटर्न के अनुसार परिणामों को अलग करना चाहते हैं, तो आप इसे कुछ इस तरह से संशोधित कर सकते हैं

while IFS= read -r -d '' file; do
  if grep -qim1 'searchPattern1' "$file"; then
    cat "$file" >> some/other/file1
  elif grep -qim1 'searchPattern2' "$file"; then
    cat "$file" >> some/other/file2
  elif grep -qim1 'searchPattern3' "$file"; then
    cat "$file" >> some/other/file3
  fi
done < <(find ./recup*/ -name '*.txt' -print0)

"किया" करने के बाद बिट क्या करता है? मैं वास्तव में ऐसा करना चाहता हूं कि अगर वह ब्लॉक हो जाए तो जिन फाइलों में एक मिलान किया हुआ पैटर्न होता है, उन्हें अलग तरह से लिखा जाता है।
अमी

यह सिर्फ '.txt' फाइलों को सूचीबद्ध करता है, जो प्रत्येक को अशक्त वर्ण द्वारा समाप्त किया जाता है (ताकि यह रिक्त स्थान और अन्य वर्णों के फ़ाइल नाम के लिए सुरक्षित हो)। whileपाश तो है कि सूचियों पढ़ता है और करता है grep/ सशर्त catभाग।
स्टीलड्राइवर

जब मैं कोड को चलाने का प्रयास करता हूं, तो मुझे यह त्रुटि मिलती है :/recoverData.sh: सिंटैक्स त्रुटि: ("अनपेक्षित। जो कि खोज कमांड के चारों ओर कोष्ठक से आ रही है
अमी

आप किस खोल का उपयोग कर रहे हैं? प्रक्रिया प्रतिस्थापन सिंटैक्स बैश करने के लिए विशिष्ट है - इसलिए मेरी योग्यता "आपके शेल और पर्यावरण के आधार पर"
स्टीलड्राइवर

1
आप या तो कमांड (एस) को सीधे एक इंटरैक्टिव बैश शेल में निष्पादित कर सकते हैं, या उन्हें एक फ़ाइल में रख सकते हैं, जिसकी पहली पंक्ति में शेबंग होता है #!/bin/bash, इसे निष्पादन योग्य बनाते हैं chmod +x recoverData.sh, और इसका उपयोग करके निष्पादित करते हैं ./recoverData.sh। करो नहीं का उपयोग sh recoverData.shके बाद से /bin/shहोने की संभावना एक है dashखोल
इस्पात
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.