Boruda başka bir katran dosyası oluşturarak tar dosyasının içeriğini nasıl filtreleyebilirim?


13

İzinleri, mtimes, vb. Gibi saklamak istediğim çeşitli özniteliklere sahip bazı dizinler içeren harici bir sistemden tek bir tar dosyasını düşünün.

Şuna benzer bir şey mi arıyorsunuz:

tar -f some.tar.gz --subset subdir/ | ssh remote@system tar xvz

Bu katran arşivindeki ana özelliklerin (sahiplik, grup, mod, mtime) korunması da önemlidir. Bir tar dosyasındaki genişletilmiş başlık anahtar kelimeleri gibi diğer öznitelikler ne olacak ?

Bu alt dizinin büyük dosyalar içermesi durumunda geçici bir dizinin kullanılmasını önleyen bir çözüm için bonus puan.

Yanıtlar:


14

bsdtar (libarchive temelli) katranı (ve diğer bazı arşivleri) stdin'den stdout'a filtreleyebilir. Örneğin , yalnızca bir kalıpla eşleşen dosya adlarından geçebilir ve s/old/new/yeniden adlandırma yapabilir . Zaten çoğu dağıtım için paketlenmiştir, örneğin bsdtarUbuntu'da olduğu gibi .

sudo apt-get install bsdtar   # or aptitude, if you have it.

# example from the man page:
bsdtar -c -f new.tar --include='*foo*' @old.tgz
#create new.tar containing only entries from old.tgz containing the string ‘foo’
bsdtar -czf - --include='*foo*' @-  # filter stdin to stdout, with gzip compression of output.

Giriş / çıkış için geniş bir sıkıştırma formatı seçeneğine sahip olduğunu unutmayın, bu nedenle gunzip / lz4'ü manuel olarak borulamanıza gerek yoktur. Sen kullanabilirsiniz -ile stdin'i için @tarfileve / veya, sözdizimi -normal gibi stdout için.


Aramam ayrıca, javascript kullanarak istediğiniz arşiv değişikliklerini tanımlamanızı isteyen bu akış katranı değiştirme aracını da buldu. (Sanırım her şey js ile yazılmış).

https://github.com/mafintosh/tar-stream


1
Mükemmel, bu @original.taryaklaşımın bsdtar ile mümkün olduğunu bilmiyordum. Genişletilmiş öznitelikler ve sıkıştırma ile de çalışıyor gibi görünüyor </var/cache/pacman/pkg/libuv-1.7.0-1-x86_64.pkg.tar.xz bsdtar -czf - --include='usr/share/*' @- | tar tvz(ve bir nedenden dolayı boş bir seçim bir dizi sıfır bayt üretiyor, ancak bu benim için büyük bir sorun değil).
Lekensteyn

1
Benim testlere göre, s/old/new/ gelmez kullanarak eski arşivlerinden gelen dosyalar üzerinde çalışmak @ old.tgz, sadece dosya sistemi doğrudan arşivleme, gerçek dosyalar üzerinde çalışır. Benim için en faydalı kullanım durumu olacağı için gerçekten utanç verici.
bart

4

En kolay yol tüm arşivi kopyalamak olacaktır; Sanırım bunu yapmak istemiyorsunuz çünkü çok büyük.

Genel komut satırı araçları ( tar, pax) bir arşivin üyelerini başka bir arşive kopyalamayı desteklemez.

Sahipliği korumanız gerekmiyorsa, FUSE dosya sistemlerini kullanmanızı öneririm . Arşivi dosya sistemi olarak monte etmek için archivemount'u kullanabilirsiniz ; bunu kaynak arşivi için yapın ve bağlı dosya sisteminde tar çalıştırın.

archivemount some.tar.gz mnt
cd mnt
tar -cz subdir | ssh example.com tar -xz
fusermount -u mnt

Alternatif olarak, AVFS kullanabilirsiniz :

mountavfs
cd ~/.avfs$PWD/some.tar.gz\#
tar -cz subdir | ssh example.com tar -xz

Alternatif olarak, tarorijinal arşivde çalışabilir ve SSHFS üzerinden uzak makineye ayıklayabilirsiniz .

sshfs example.com: mnt
cd mnt
tar -xf /path/to/some.tar.gz subdir
fusermount -u mnt

Ancak, sahipliğinizi korumanız gerekiyorsa, tüm bu yöntemler hantaldır. Hepsi yerel makinedeki bir dosyaya çıkarmayı içerir, bu nedenle bu dosyanın sahipliği istenen uzak sahiplik olmalıdır. Bu, root olarak çalışmayı gerektirir ve dosyalar yerel makine ile uzak ana makine arasında farklılık gösteren adlara veya kimliklere sahip hesaplara sahipse, amaçlanan sonucu vermeyebilir.

Python'un tarfilekütüphanesi, katran üyelerini manipüle etmek için oldukça kolay bir yol sağlar, böylece onları bir katran dosyasından diğerine karıştırabilirsiniz. POSIX standart biçimlerini (ustar, pax) ve bazı GNU uzantılarını destekler. İşte standart girdisinde bir tar dosyasını (muhtemelen gzip veya bzip2 ile sıkıştırılmış) okuyan ve bzip2 ile sıkıştırılmış bir tar dosyasını standart çıktısına yazan test edilmemiş bir Python betiği. Kaynaktan üyeler, betiğe iletilen bağımsız değişkenle başlarlarsa kopyalanır.

#!/usr/bin/env python2
import sys, tarfile
source = tarfile.open(fileobj=sys.stdin)
destination = tarfile.open(fileobj=sys.stdout, mode='w:bz2')
for info in source:
    if info.name.startswith(sys.argv[1]):
        destination.addfile(info)
destination.close()

Olarak çağrılmak

tar_filter <some.tar.gz subdir/ | ssh example.com tar -xj

1
bsdtar (libarchive tabanlı) katran arşivlerini anında filtreleyebilir, cevabımı görün.
Peter Cordes

Görev, bir bellenim görüntüsünden veri çıkarmaktı, bu nedenle sahiplik / grup üyeliği gerçekten önemlidir. Python yaklaşımı da işe yarayabilir.
Lekensteyn

0

Alternatif ayrıcalıksız bir yaklaşım, fakerootprogramı sahiplik değiştirme izniniz olduğunu iddia etmek için kullanmaktır . Diğer katran nitelikleri kaybolurken, modu, mtime ve uid / gid işlevlerini korur. Bu komutlar geçici bir dizin oluşturur, dosyaların bir alt kümesini çıkarır ve son olarak yeni bir arşiv oluşturur:

mkdir tmp
<some.tar.gz \
fakeroot -- sh -c 'cd tmp && tar -xzf- subdir/ && tar -czf- subdir' |
   ssh remote@system tar -xzvf-
rm -rf tmp

0

GNU'nun tarbir --deleteseçeneği var:

$ tar -c a b c | tar --delete a | tar -t
b
c

Bu şekilde, çıktıya neyin dahil edilmeyeceğini belirterek girdi katranının bir alt kümesini elde edebilirsiniz .

Ne yazık ki --exclude, çalışma seçeneği alamadım --delete, bu yüzden önce -tsilmek için şeylerin açık bir listesini ( ) almak ve daha sonra başka bir çağrı geçmek gibi görünüyor tar.

$ tar --delete --no-recursion `tar -t --exclude subdir <some.tar` <some.tar | ssh ...

Veya çok uzun veya karmaşıksa listeyi harici bir dosyada saklayabilirsiniz:

$ tar -t --exclude subdir <some.tar >to_delete.lst
$ tar --delete --no-recursion -T to_delete.lst <some.tar | ssh ...

-1

Bildiğim kadarıyla, tarkomut tar biçimini hem girdi hem de çıktı olarak kullanamaz . Dosyalarınızı bir şekilde yerel olarak ayıklamanız ve anında tarfile oluşturmak için tar gibi bir şey kullanmanız gerekecektir -(bir dosya yerine standart girdi / çıktı kullanıldığı anlamına gelir):

tar cf - subdir/ | ssh remote@system 'cd extractdir && tar xvf -'

Sahip unutmayın tarbaşka tarfile doğrudan tarfile çıkarabilme ilginç bir fikir ...


Kök olmadan bu açıkça tutmak istediğim tüm sahiplik / grup bilgilerini kaybeder.
Lekensteyn

1
Sorunuzu, ana makinenizde kök erişiminiz olmadığını içerecek şekilde düzenlemelisiniz.
Uriel
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.