कुशलता से फ़ाइल को बड़े .tgz से हटाएं


14

मान लें कि मेरे पास एक gzip संपीड़ित टार-बॉल संपीड़ित है। Trz (+100 फाइलें, कुल + 5 जीबी)।

उपसर्ग * .jpg के लिए दिए गए फ़ाइल नाम पैटर्न से मेल खाते सभी प्रविष्टियों को हटाने का सबसे तेज़ तरीका क्या होगा। फिर gzip में अवशेषों को संग्रहीत करें: फिर से एड-बॉल?

पुराने संग्रह को बदलना या नया बनाना महत्वपूर्ण नहीं है, जो भी सबसे तेज़ हो।


जवाबों:


14

GNU के साथ tar, आप यह कर सकते हैं:

pigz -d < file.tgz |
  tar --delete --wildcards -f - '*/prefix*.jpg' |
  pigz > newfile.tgz

के साथ bsdtar:

pigz -d < file.tgz |
  bsdtar -cf - --exclude='*/prefix*.jpg' @- |
  pigz > newfile.tgz

( pigzबहु थ्रेडेड संस्करण के होने के नाते gzip)।

आप फ़ाइल को अपने आप से अधिलेखित कर सकते हैं जैसे:

{ pigz -d < file.tgz |
    tar --delete --wildcards -f - '*/prefix*.jpg' |
    pigz &&
    perl -e 'truncate STDOUT, tell STDOUT'
} 1<> file.tgz

लेकिन यह काफी जोखिम भरा है, खासकर यदि परिणाम मूल फ़ाइल की तुलना में कम संपीड़ित हो रहा है (जिस स्थिति में, दूसरा pigzफ़ाइल के ओवरराइटिंग क्षेत्रों को समाप्त कर सकता है जो पहले एक ने अभी तक नहीं पढ़ा है)।


उत्तर के लिए धन्यवाद, उत्कीर्ण। अगले सप्ताह बेंचमार्क चलाएंगे, यह देखने के लिए कि कौन सा मेरे संग्रह और सिस्टम के लिए बेहतर प्रदर्शन करता है और इसे स्वीकार करता है।
अक्सेल विलगर्ट

8

आसान तरीके से छूट न दें: यह आपके उद्देश्य के लिए पर्याप्त तेज़ हो सकता है। एक निर्देशिका के रूप में संग्रह को एक्सेस करने के लिए avfs के साथ :

cd ~/.avfs/path/to/original.tar.gz\#
pax -w -s '/^.*\.jpg$//' | gzip >/path/to/filtered.tar.gz        # POSIX
tar -czf /path/to/filtered.tar.gz -s '/^.*\.jpg$//' .            # BSD
tar -czf /path/to/filtered.tar.gz --transform '/^.*\.jpg$//' .   # GNU

अधिक आदिम उपकरणों के साथ, पहले फाइलों को छोड़कर फाइलें निकालें .jpg, फिर एक नया संग्रह बनाएं।

mkdir tmpdir && cd tmpdir
<original.tar.gz gzip -d | pax -r -pe -s '/^.*\.jpg$//'
pax -w . | gzip >filtered.tar.gz
cd .. && rm -rf tmpdir

यदि आपके टार में है --exclude:

mkdir tmpdir && cd tmpdir
tar -xzf original.tar.gz --exclude='*.jpg'
tar -czf filtered.tar.gz .
cd .. && rm -rf tmpdir

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

अभिलेखागार के लिए एक पास-थ्रू के रूप में कार्य करने का समर्थन (यानी एक संग्रह पढ़ें और एक संग्रह लिखें) सीमित हो जाता है। GNU टार --deleteऑपरेशन ऑप्शन के साथ एक आर्काइव से सदस्यों को हटा सकता है (“ --deleteविकल्प को ठीक से काम करने के लिए सूचित किया गया है जब tarसे फिल्टर के रूप में कार्य करता stdinहैstdout ।"), और कहा कि शायद आपका सबसे अच्छा विकल्प है।

आप पायथन की कुछ पंक्तियों में शक्तिशाली संग्रह फ़िल्टर बना सकते हैं। इसकी tarfileलाइब्रेरी गैर-शोध योग्य धाराओं से पढ़ और लिख सकती है, और आप पायथन में मनमाने कोड का उपयोग फ़िल्टर करने, नाम बदलने, संशोधित करने…

#!/usr/bin/python
import re, sys, tarfile
source = tarfile.open(fileobj=sys.stdin, mode='r|*')
dest = tarfile.open(fileobj=sys.stdout, mode='w|gz')
for member in source:
    if not (member.isreg() and re.match(r'.*\.jpg\Z', member.name)):
        sys.stderr.write(member.name + '\n')
        dest.addfile(member, source.extractfile(member))
dest.close()

यह यूआईडी / यूज़रनेम को भी रूट करेगा जब तक कि इसे रूट के रूप में नहीं चलाया जाता है जब तक कि यह एक ऐसी मशीन पर नहीं किया जाता है जिसमें एक ही यूआईडी है <=> उपयोगकर्ता नाम मैपिंग जहां टार फ़ाइल शुरू में बनाई गई थी। ACLs, विस्तारित विशेषताएँ भी प्रभावित हो सकती हैं। इसके साथ tar, आप pविकल्प जोड़ना चाह सकते हैं ।
स्टीफन चेज़लस

2

मैक OSX पर आने वाले टार के साथ, आप ऐसा कर सकते हैं:

tar -czf b.tgz --exclude '*.jpg' @a.tgz
mv b.tgz a.tgz

1

ऐसा करने के लिए, आपको संभवतः स्थानीय dir में .tgz फ़ाइल के सभी कंटीनेंट को निकालना होगा फिर उन फ़ाइलों को मिटा दें जिन्हें आप नहीं चाहते हैं।

यह लंबा है और आपको पर्याप्त रूप से मुक्त डिस्क स्थान की आवश्यकता है लेकिन मेरे ज्ञान का सबसे अच्छा करने के लिए, इसे करने का कोई अन्य तरीका नहीं है।

यह देखते हुए कि आपके पास पहले से ही कुछ रास्ता है जैसे /tmpdir/withalotofspaceकि पर्याप्त जगह खाली है (इसका उपयोग करके जांच करें df -h /tmpdir/withalotofspace), आप कुछ इस तरह कर सकते हैं:

$ cd /tmpdir/withalotofspace
$ tar -xvfz /path/to/compressedArchive.tgz
$ find /tmpdir/withalotofspace/ -type f -iname '*.jpg' -delete
$ tar -cvzf /path/to/purgedcompressedArchive.tgz .

अन्य उत्तरों के रूप में, पाइपिंग के माध्यम से डिस्क पर असम्पीडित डेटा को किसी भी बिंदु पर संग्रहीत करने की आवश्यकता नहीं है
तोबियस किंजलर

0

मुझे @Gilles का जवाब पसंद है, सिवाय इसके कि इसे और सरल बनाया जा सकता है। अनज़िप करने के बाद, उदाहरण के gunzip foo.tgzलिए फ़ाइल होगी foo.tarऔर फ़ाइलों को हटाया जा सकता है tar -f foo.tar --delete file|directory। नीचे एक टार फ़ाइल से निर्देशिका को हटाने का एक उदाहरण है।

    phablet@ubuntu-phablet:~/Downloads$ tar -cvf moo.tar moo1/
    moo1/
    moo1/moo2/
    moo1/moo2/moo3/
    moo1/moo2/moo3/moo4/
    moo1/moo2/moo3/moo4/moo5/
    phablet@ubuntu-phablet:~/Downloads$ tar -tf moo.tar 
    moo1/
    moo1/moo2/
    moo1/moo2/moo3/
    moo1/moo2/moo3/moo4/
    moo1/moo2/moo3/moo4/moo5/
    phablet@ubuntu-phablet:~/Downloads$ tar -f moo.tar --delete "moo1/moo2/moo3"
    phablet@ubuntu-phablet:~/Downloads$ tar -tf moo.tar 
    moo1/
    moo1/moo2/

विशिष्ट फ़ाइल प्रकारों के साथ पाया जा सकता है tar -tf foo.tar|egrep -i '.jpg$'

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