考虑来自外部系统的单个 tar 文件,其中包含一些具有各种属性的目录,我希望保留这些属性,例如权限、mtimes 等。如何以普通用户(不是 root)的身份轻松获取这些文件的子集?
寻找类似的东西:
tar -f some.tar.gz --subset subdir/ | ssh remote@system tar xvz
Run Code Online (Sandbox Code Playgroud)
保留此 tar 存档中的主要属性(所有权、组、模式、mtime)也很重要。tar 文件中的其他属性(例如扩展标头关键字)呢?
避免使用临时目录的解决方案的加分点,以防此子目录包含大文件。
Pet*_*des 15
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.
Run Code Online (Sandbox Code Playgroud)
请注意,输入/输出的压缩格式有多种选择,因此您不必自己手动通过 gunzip / lz4 进行管道传输。您可以使用-带有@tarfile语法的stdin ,和/或-像平常一样用于 stdout。
我的搜索还发现了这个流式 tar 修改工具,它似乎希望您使用 javascript 定义您想要的存档更改。(我认为整个事情都是用 js 编写的)。
https://github.com/mafintosh/tar-stream
最简单的方法是复制整个档案;我想你不想这样做,因为它太大了。
常用的命令行工具(tar、pax)不支持将一个存档的成员复制到另一个存档。
如果您不需要保留所有权,我建议使用FUSE文件系统。您可以使用archivemount将存档挂载为文件系统;对源存档执行此操作,并在已安装的文件系统上运行 tar。
archivemount some.tar.gz mnt
cd mnt
tar -cz subdir | ssh example.com tar -xz
fusermount -u mnt
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用AVFS:
mountavfs
cd ~/.avfs$PWD/some.tar.gz\#
tar -cz subdir | ssh example.com tar -xz
Run Code Online (Sandbox Code Playgroud)
或者,您可以在原始存档上运行并通过SSHFStar提取到远程计算机。
sshfs example.com: mnt
cd mnt
tar -xf /path/to/some.tar.gz subdir
fusermount -u mnt
Run Code Online (Sandbox Code Playgroud)
然而,如果您需要保留所有权,所有这些方法都很麻烦。它们都涉及提取到本地计算机上的文件,因此该文件的所有权必须是预期的远程所有权。这需要以 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()
Run Code Online (Sandbox Code Playgroud)
被调用为
tar_filter <some.tar.gz subdir/ | ssh example.com tar -xj
Run Code Online (Sandbox Code Playgroud)