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


11

सबसे अच्छा मैं इस तरह से कॉल करना चाहूंगा:

$searchtool /path/to/search/ -contained-file-name "*vacation*jpg"

... ताकि यह उपकरण

  • दिए गए पथ का पुनरावर्ती स्कैन करता है
  • समर्थित संग्रह प्रारूपों के साथ सभी फाइलें लेता है जो कम से कम "सबसे आम" होना चाहिए जैसे ज़िप, आरएआर, 7z, tar.bz, tar.gz ...
  • और प्रश्न में नाम पैटर्न के लिए संग्रह की फ़ाइल सूची को स्कैन करें (यहां *vacation*jpg)

मुझे पता है कि कैसे खोज उपकरण, टार, अनज़िप और एक जैसे का उपयोग करें। मैं इन्हें एक शेल स्क्रिप्ट के साथ जोड़ सकता हूं, लेकिन मैं एक सरल समाधान की तलाश कर रहा हूं जो कि शेल वन-लाइनर या समर्पित टूल हो सकता है (GUI टूल के लिए संकेत स्वागत है लेकिन मेरा समाधान कमांड लाइन आधारित होना चाहिए)।

जवाबों:


9

( मैं कैसे संग्रहीत अभिलेखागार के माध्यम से पुनरावृत्ति grep से अनुकूलित ? )

AVFS , एक फाइल सिस्टम स्थापित करें जो अभिलेखागार के अंदर पारदर्शी पहुंच प्रदान करता है। अपनी मशीन के फ़ाइल सिस्टम का एक दृश्य सेट करने के लिए पहले इस कमांड को चलाएं जिसमें आप अभिलेखागार तक पहुँच सकते हैं जैसे कि वे निर्देशिका थे:

mountavfs

इसके बाद, यदि /path/to/archive.zipकोई मान्यता प्राप्त संग्रह है, तो ~/.avfs/path/to/archive.zip#एक निर्देशिका है जिसमें संग्रह की सामग्री सम्‍मिलित है।

find ~/.avfs"$PWD" \( -name '*.7z' -o -name '*.zip' -o -name '*.tar.gz' -o -name '*.tgz' \) \
     -exec sh -c '
                  find "$0#" -name "*vacation*.jpg"
                 ' {} 'Test::Version' \;

स्पष्टीकरण:

  • AVFS फाइलसिस्टम को माउंट करें।
  • संग्रह फ़ाइलों के लिए देखें ~/.avfs$PWD, जो वर्तमान निर्देशिका का AVFS दृश्य है।
  • प्रत्येक संग्रह के लिए, निर्दिष्ट शेल स्निपेट (खोज के लिए $0= संग्रह नाम और $1= पैटर्न के साथ) निष्पादित करें ।
  • $0#संग्रह का निर्देशिका दृश्य है $0
  • {\}बजाय {}जरूरत के मामले में बाहरी findविकल्प बहस के {}अंदर -exec ;(कुछ यह करते हैं, कुछ नहीं)।

या zsh ≥4.3 में:

mountavfs
ls -l ~/.avfs$PWD/**/*.(7z|tgz|tar.gz|zip)(e\''
     reply=($REPLY\#/**/*vacation*.jpg(.N))
'\')

स्पष्टीकरण:

  • ~/.avfs$PWD/**/*.(7z|tgz|tar.gz|zip) वर्तमान निर्देशिका और इसके उपनिर्देशिकाओं के AVFS दृश्य में अभिलेखागार से मेल खाता है।
  • PATTERN(e\''CODE'\')पैटर्न के प्रत्येक मैच के लिए कोड लागू होता है। मिलान की गई फ़ाइल का नाम है $REPLYreplyसरणी सेट करना मैच को नामों की सूची में बदल देता है।
  • $REPLY\# संग्रह का निर्देशिका दृश्य है।
  • $REPLY\#/**/*vacation*.jpg*vacation*.jpgसंग्रह में फ़ाइलों से मेल खाता है ।
  • Nग्लोब क्वालीफायर पैटर्न बनाता है एक खाली सूची का विस्तार अगर कोई मुकाबला नहीं है।

9

यदि आप कुछ सरल चाहते हैं जो एवीएफएस समाधान, मैंने इसे करने के लिए एक पायथन स्क्रिप्ट लिखी जिसे इसे अर्कफ्रंट कहा जाता है । आप वास्तव में बस कर सकते हैं

$ arkfind /path/to/search/ -g "*vacation*jpg"

यह पुनरावर्ती रूप से करेगा, इसलिए आप अभिलेखागार के अंदर अभिलेखों को एक मनमाना गहराई तक देख सकते हैं।


धन्यवाद, अच्छा योगदान! खासकर अगर एवीएफएस कोई विकल्प नहीं है।
मडो जूल 5'13

यह बहुत अच्छा होगा अगर यह जार फाइलों का समर्थन करता है।
केमिक

@ शेमिक - नोट किया ! मैं इस सप्ताह के अंत में इस पर थोड़ा और काम करूंगा :) जार बहुत मुश्किल नहीं होना चाहिए, मेरा मानना ​​है कि यह वास्तव में बाहरी दुनिया के लिए सिर्फ एक ज़िप फ़ाइल है।
detly

@ किमिक - मैंने अभी इसकी कोशिश की, और इसे वैसे भी अपने वर्तमान स्वरूप में JAR फ़ाइलों का समर्थन करना चाहिए। क्या आप इसका परीक्षण कर सकते हैं, और यदि यह अपेक्षा के अनुरूप काम नहीं करता है, तो जीथब पृष्ठ पर बग दर्ज करें? (मैं सिर्फ एक बग को ठीक करता था, इसलिए अपनी कॉपी को अपडेट करना सुनिश्चित करें।)
जासूसी करें

1
हां अब मैं देख रहा हूं, यह काम करता है। आप README पर "JAR फाइलें" जोड़ सकते हैं :)
कैमिक

2

मेरा सामान्य समाधान:

find -iname '*.zip' -exec unzip -l {} \; 2>/dev/null | grep '\.zip\|DESIRED_FILE_TO_SEARCH'

उदाहरण:

find -iname '*.zip' -exec unzip -l {} \; 2>/dev/null | grep '\.zip\|characterize.txt'

रेज़ल्स इस प्रकार हैं:

foozip1.zip:
foozip2.zip:
foozip3.zip:
    DESIRED_FILE_TO_SEARCH
foozip4.zip:
...

यदि आप इस पर हिट के साथ केवल ज़िप फ़ाइल चाहते हैं :

find -iname '*.zip' -exec unzip -l {} \; 2>/dev/null | grep '\.zip\|FILENAME' | grep -B1 'FILENAME'

यहां FILENAME का उपयोग दो बार किया जाता है, इसलिए आप एक चर का उपयोग कर सकते हैं।

खोजने के साथ आप PATH / TO / SEARCH का उपयोग कर सकते हैं



2

IMHO उपयोगकर्ता मित्रता के रूप में अच्छी तरह से बात में होना चाहिए:

 while read -r zip_file ; do echo "$zip_file" ; unzip -l "$zip_file" | \
 grep -i --color=always -R "$to_srch"; \
 done < <(find . \( -name '*.7z' -o -name '*.zip' \)) | \
 less -R

और टार के लिए (यह एक अप्रयुक्त है ...)

 while read -r tar_file ; do echo "$tar_file" ; tar -tf  "$tar_file" | \
 grep -i --color=always -R "$to_srch"; \
 done < <(find . \( -name '*.tar.gz' -o -name '*.tar' \)) | \
 less -R

क्या unzipकार्यान्वयन 7z या tar.gz फाइलों से निपट सकता है?
स्टीफन चेजलस

हाँ, यह एक बग है ... सही किया गया है ... एक को निश्चित रूप से सही फ़ाइल प्रकारों के लिए सही बायनेरिज़ का उपयोग करना चाहिए ... मैं सिर्फ एक-लाइनर प्रदर्शित करने का लक्ष्य रखता हूं .. यह एक लगभग तैयार होने की स्थिति में पहुंच जाएगा के रूप में कैसे प्राप्त करने के लिए ...
Yordan Georgiev

0

libarchiveके bsdtarउन फ़ाइल स्वरूपों के सबसे संभाल कर सकते हैं, तो आप कर सकता है:

find . \( -name '*.zip' -o     \
          -name '*.tar' -o     \
          -name '*.tar.gz' -o  \
          -name '*.tar.bz2' -o \
          -name '*.tar.xz' -o  \
          -name '*.tgz' -o     \
          -name '*.tbz2' -o    \
          -name '*.7z' -o      \
          -name '*.iso' -o     \
          -name '*.cpio' -o    \
          -name '*.a' -o       \
          -name '*.ar' \)      \
       -type f                 \
       -exec bsdtar tf {} '*vacation*jpg' \; 2> /dev/null

जिसे आप सरल कर सकते हैं (और केस-असंवेदनशील रूप से मिलान करने के लिए सुधार कर सकते हैं) GNU के findसाथ:

find . -regextype egrep \
       -iregex '.*\.(zip|7z|iso|cpio|ar?|tar(|\.[gx]z|\.bz2)|tgz|tbz2)' \
       -type f \
       -exec bsdtar tf {} '*vacation*jpg' \; 2> /dev/null

यह संग्रह के पथ को मुद्रित नहीं करता है, जहाँ उन *vacation*jpgफ़ाइलों को पाया जाता है। उस नाम को मुद्रित करने के लिए जिसे आप अंतिम पंक्ति से बदल सकते हैं:

-exec sh -ac '
   for ARCHIVE do
     bsdtar tf "$ARCHIVE" "*vacation*jpg" |
       awk '\''{print ENVIRON["ARCHIVE"] ": " $0}'\''
   done' sh {} + 2> /dev/null

जो एक आउटपुट देता है जैसे:

./a.zip: foo/blah_vacation.jpg
./a.zip: bar/blih_vacation.jpg
./a.tar.gz: foo/blah_vacation.jpg
./a.tar.gz: bar/blih_vacation.jpg

या साथ zsh:

setopt extendedglob # best in ~/.zshrc
for archive (**/*.(#i)(zip|7z|iso|cpio|a|ar|tar(|.gz|.xz|.bz2)|tgz|tbz2)(.ND)) {
  matches=("${(f@)$(bsdtar tf $archive '*vacation*jpg' 2> /dev/null)"})
  (($#matches)) && printf '%s\n' "$archive: "$^matches
}

नोट अन्य फ़ाइल स्वरूप है कि बस कर रहे हैं की एक संख्या देखते हैं कि zipया tgzकी तरह भेस में फ़ाइलें .jarया .docxफ़ाइलों। आप उन्हें अपने find/ zshखोज पैटर्न में जोड़ सकते हैं , bsdtarविस्तार के बारे में परवाह नहीं करते हैं (जैसा कि, यह फ़ाइल के प्रकार को निर्धारित करने के लिए विस्तार पर निर्भर नहीं करता है)।

ध्यान दें कि *vacation*.jpgऊपर पूर्ण संग्रह सदस्य पथ पर मिलान किया गया है, न कि केवल फ़ाइल नाम, इसलिए यह पर vacation.jpgभी मेल खाएगा vacation/2014/file.jpg

केवल फ़ाइल नाम पर मिलान करने के लिए, एक चाल अर्क मोड का उपयोग करना होगा , -s(प्रतिस्थापन) जो pमिलान फ़ाइलों के नाम प्रिंट करने के लिए एक ध्वज के साथ regexps का उपयोग करता है और फिर सुनिश्चित करें कि कोई फ़ाइल नहीं निकाली गई है, जैसे:

bsdtar -'s|.*vacation[^/]*$||' -'s|.*||' -xf "$archive"

ध्यान दें कि यह stderr पर सूची को आउटपुट करेगा और >>हर पंक्ति में संलग्न करेगा। किसी भी मामले में bsdtar, जैसे अधिकांश tarकार्यान्वयन प्रदर्शन पर फ़ाइल नामों को जोड़ सकते हैं, यदि उनके पास कुछ वर्ण होते हैं जैसे कि newline या backslash (के रूप में प्रदान किया गया ) \nया \\

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