Найпростішим способом було б скопіювати весь архів; Я припускаю, що ти цього не хочеш робити, тому що він занадто великий.
Звичайні засоби командного рядка ( tar
, pax
) не підтримують копіювання членів архіву в інший архів.
Якщо вам не потрібно було зберігати право власності, я б запропонував використовувати файлові системи FUSE . Ви можете використовувати archivemount для монтажу архіву як файлової системи; зробіть це для архіву джерела та запустіть tar на змонтованій файловій системі.
archivemount some.tar.gz mnt
cd mnt
tar -cz subdir | ssh example.com tar -xz
fusermount -u mnt
Крім того, ви можете використовувати AVFS :
mountavfs
cd ~/.avfs$PWD/some.tar.gz\#
tar -cz subdir | ssh example.com tar -xz
Крім того, ви можете запустити tar
в оригінальному архіві та витягнути на віддалену машину через SSHFS .
sshfs example.com: mnt
cd mnt
tar -xf /path/to/some.tar.gz subdir
fusermount -u mnt
Однак усі ці методи громіздкі, якщо вам потрібно зберегти право власності. Усі вони включають витяг у файл на локальній машині, тому право власності на цей файл має бути призначеним віддаленим правом власності. Це вимагає запуску як root і може не дати наміченого результату, якщо до файлів належать облікові записи, які мають імена або ідентифікатори, які відрізняються між локальною машиною та віддаленим хостом.
tarfile
Бібліотека Python пропонує досить простий спосіб маніпулювання членами tar, тому ви можете переміщувати їх з одного файлу tar на інший. Він підтримує стандартні формати POSIX (ustar, pax), а також деякі розширення GNU. Ось неперевірений сценарій Python, який зчитує файл tar (можливо, стиснутий gzip або bzip2) на своєму стандартному вході та записує файл tar, стиснутий bzip2 на стандартному виході. Члени з джерела копіюються, якщо вони починають з аргументу, переданого до сценарію.
#!/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()
Щоб викликати як
tar_filter <some.tar.gz subdir/ | ssh example.com tar -xj
@original.tar
підхід можливий за допомогою bsdtar. Здається, працює і з розширеними атрибутами та стисненням</var/cache/pacman/pkg/libuv-1.7.0-1-x86_64.pkg.tar.xz bsdtar -czf - --include='usr/share/*' @- | tar tvz
(і чомусь порожній вибір виділяє серію нульових байтів, але це не є для мене головною проблемою).