Answers:
bsdtar(基于libarchive)可以将tar(和其他一些归档文件)从stdin过滤到stdout。例如,它只能传递与模式匹配的文件名,并且可以s/old/new/
重命名。它已经打包用于大多数发行版,例如bsdtar
在Ubuntu中。
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.
请注意,输入/输出有多种压缩格式供选择,因此您不必自己手动通过gunzip / lz4进行管道传输。您可以将-
stdin与@tarfile
语法一起使用,和/或-
将stdout像平常一样使用。
我的搜索还找到了此流式tar修改工具,该工具似乎希望您使用javascript定义所需的存档更改。(我认为整个事情都是用js编写的)。
s/old/new/
不适用于使用@ old.tgz的旧档案文件,仅适用于实际文件,直接从文件系统进行归档。真的很遗憾,因为这对我来说是最有用的用例。
最简单的方法是复制整个档案。我认为您不想这样做,因为它太大了。
常用的命令行工具(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用户身份运行,并且如果文件由名称或ID在本地计算机和远程主机之间不同的帐户拥有,则可能无法获得预期的结果。
Python的tarfile
库提供了一种操作tar成员的相当简单的方法,因此您可以将它们从一个tar文件拖曳到另一个tar文件。它支持POSIX标准格式(ustar,pax)以及某些GNU扩展。这是未经测试的Python脚本,该脚本在其标准输入上读取tar文件(可能使用gzip或bzip2压缩),并在其标准输出上写入用bzip2压缩的tar文件。如果源成员以传递给脚本的参数开头,则将对其进行复制。
#!/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
GNU tar
确实有一个--delete
选择:
$ tar -c a b c | tar --delete a | tar -t
b
c
这样,您可以通过指定不包含在输出中的内容来获取输入tar的子集。
不幸的是我无法使用该--exclude
选项--delete
,因此看来您首先需要获取-t
要删除的显式列表(),然后将其传递给另一个调用tar
。
$ tar --delete --no-recursion `tar -t --exclude subdir <some.tar` <some.tar | ssh ...
或者,如果列表太长或太复杂,也可以将其存储在外部文件中:
$ tar -t --exclude subdir <some.tar >to_delete.lst
$ tar --delete --no-recursion -T to_delete.lst <some.tar | ssh ...
据我所知,该tar
命令不能使用tar格式都作为输入和输出。您将必须以某种方式在本地解压缩文件,然后再次使用tar即时创建tarfile,如下所示(-
意味着使用标准输入/输出而不是文件):
tar cf - subdir/ | ssh remote@system 'cd extractdir && tar xvf -'
请注意,tar
能够直接在另一个tarfile中提取tarfile是一个有趣的主意...
@original.tar
使用bsdtar可以实现这种方法。似乎也可以使用扩展属性和压缩,</var/cache/pacman/pkg/libuv-1.7.0-1-x86_64.pkg.tar.xz bsdtar -czf - --include='usr/share/*' @- | tar tvz
(由于某种原因,空选择会产生一系列零字节,但这对我来说不是主要问题)。