Dosyaları büyük .tgz'den verimli bir şekilde kaldırın


14

Bir gzip sıkıştırılmış tar-ball sıkıştırılmışArchive.tgz (+100 dosya, toplam + 5gb) olduğunu varsayın.

* .Jpg öneki gibi belirli bir dosya adı deseniyle eşleşen tüm girdileri kaldırmanın ve ardından kalıntıları tekrar gzip: ed tar-ball'da depolamanın en hızlı yolu nedir?

Hangisi en hızlıysa, eski arşivi değiştirmek veya yenisini oluşturmak önemli değildir.


Yanıtlar:


14

GNU ile tarşunları yapabilirsiniz:

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

İle bsdtar:

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

( pigzçok iş parçacıklı sürümüdür gzip).

Dosyanın üzerine aşağıdaki gibi yazabilirsiniz:

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

Ancak bu, özellikle sonuç orijinal dosyadan daha az sıkıştırılmışsa (bu durumda ikincisi pigz, dosyanın birincisinin henüz okumamış olduğu alanların üzerine yazılması) oldukça risklidir .


cevap için teşekkürler, iptal edildi. arşiv ve sistemim için hangisinin daha iyi performans gösterdiğini görmek ve bunu kabul etmek için gelecek hafta karşılaştırma ölçütü yayınlayacak.
Aksel Willgert

8

Kolay yolu indirmeyin: Amacınız için yeterince hızlı olabilir. İle AVF'lerin bir dizin olarak arşiv erişmek için:

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

Daha ilkel araçlarla, önce dosyalar hariç dosyaları çıkarın .jpg, ardından yeni bir arşiv oluşturun.

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

Katranınız varsa --exclude:

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

Ancak bu, root olarak çalıştırmazsanız dosya sahipliğini ve modlarını değiştirebilir. En iyi sonuçlar için, hızlı bir dosya sisteminde geçici bir dizin kullanın - yeterince büyük bir dizine sahipseniz tmpfs.

Arşivleyicilerin doğrudan geçiş görevi (yani bir arşivi okuma ve bir arşiv yazma) desteği sınırlı olma eğilimindedir. GNU tar arşiv üyeleri silebilirsiniz ile --deleteoperasyon seçeneği ( “ --deletezaman seçenek düzgün çalışması bildirilmiştir targelen bir filtre görevi görür stdinetmek stdout.”), Ve muhtemelen en iyi seçenek bu.

Birkaç Python satırında güçlü arşiv filtreleri oluşturabilirsiniz. Onun tarfilekütüphane okuyup olmayan seekable derelerden yazma, ve değiştirmek, filtre, yeniden adlandırma Python rasgele kod kullanabilirsiniz edebilirsiniz ...

#!/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()

Ayrıca, tar dosyasının ilk oluşturulduğu ile aynı uid <=> kullanıcı adı eşlemesine sahip bir makinede yapılmadıkça, root olarak çalıştırılırsa uid / usernames'i değiştirir. EKL'ler, genişletilmiş özellikler de etkilenebilir. İle seçeneği tareklemek isteyebilirsiniz p.
Stéphane Chazelas

2

Mac OSX'te gelen katranla bunu yapabilirsiniz:

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

1

Bunu yapmak için, yerel bir dizinde .tgz dosyasının tüm içeriğini ayıklamanız ve sonra istemediğiniz dosyaları silmeniz ve sonra .tgz'yi yeniden sıkıştırmanız gerekir.

Çok uzun ve yeterli boş disk alanına ihtiyacınız var ama bilgim dahilinde bunu yapmanın başka bir yolu yok.

Zaten /tmpdir/withalotofspaceyeterli boş alana sahip gibi bir yolunuz olduğu göz önüne alındığında (kullanarak kontrol edin df -h /tmpdir/withalotofspace), böyle bir şey yapabilirsiniz:

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

Diğer cevapların gösterdiği gibi, borulama yoluyla, sıkıştırılmamış verilerin herhangi bir noktada diskte depolanmasına gerek yoktur
Tobias Kienzler

0

@Gilles'ın cevabını seviyorum, ancak daha da basitleştirilebilir. Sıkıştırdıktan sonra, örneğin gunzip foo.tgzdosya olacak foo.tarve dosyalar ile birlikte kaldırılabilir tar -f foo.tar --delete file|directory. Aşağıda bir dizinin tar dosyasından kaldırılmasına bir örnek verilmiştir.

    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/

Belirli dosya türleri ile bulunabilir tar -tf foo.tar|egrep -i '.jpg$'.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.