假设我有一个 gzip 压缩的 tar-ballcompressedArchive.tgz(+100 个文件,总计 +5gb)。
删除与给定文件名模式匹配的所有条目(例如 prefix*.jpg),然后将剩余部分再次存储在 gzip:ed tar-ball 中的最快方法是什么?
替换旧存档或创建新存档并不重要,以最快的为准。
Sté*_*las 15
使用 GNU tar
,您可以执行以下操作:
pigz -d < file.tgz |
tar --delete --wildcards -f - '*/prefix*.jpg' |
pigz > newfile.tgz
Run Code Online (Sandbox Code Playgroud)
与bsdtar
:
pigz -d < file.tgz |
bsdtar -cf - --exclude='*/prefix*.jpg' @- |
pigz > newfile.tgz
Run Code Online (Sandbox Code Playgroud)
(pigz
作为 的多线程版本gzip
)。
您可以覆盖文件本身,例如:
{ pigz -d < file.tgz |
tar --delete --wildcards -f - '*/prefix*.jpg' |
pigz &&
perl -e 'truncate STDOUT, tell STDOUT'
} 1<> file.tgz
Run Code Online (Sandbox Code Playgroud)
但这相当危险,特别是如果结果最终比原始文件压缩得少(在这种情况下,第二个pigz
可能最终覆盖第一个尚未读取的文件区域)。
不要轻视简单的方法:它可能足够快满足您的目的。使用avfs将存档作为目录访问:
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
Run Code Online (Sandbox Code Playgroud)
使用更原始的工具,首先提取不包括.jpg
文件的文件,然后创建一个新的存档。
mkdir tmpdir && cd tmpdir
<original.tar.gz gzip -d | pax -r -pe -s '/^.*\.jpg$//'
pax -w . | gzip >filtered.tar.gz
cd .. && rm -rf tmpdir
Run Code Online (Sandbox Code Playgroud)
如果您的 tar 有--exclude
:
mkdir tmpdir && cd tmpdir
tar -xzf original.tar.gz --exclude='*.jpg'
tar -czf filtered.tar.gz .
cd .. && rm -rf tmpdir
Run Code Online (Sandbox Code Playgroud)
但是,如果您不以 root 身份运行它,这可能会破坏文件所有权和模式。为获得最佳效果,请在快速文件系统上使用临时目录 — tmpfs 如果您有足够大的文件系统。
对存档器作为传递(即读取存档和写入存档)的支持往往是有限的。GNU tar 可以使用--delete
操作选项从存档中删除成员(“--delete
据报告,该选项tar
作为过滤器从stdin
到stdout
.”时可以正常工作),这可能是您最好的选择。
您可以使用几行 Python 代码创建强大的存档过滤器。它的tarfile
库可以从不可搜索的流中读取和写入,你可以使用 Python 中的任意代码来过滤、重命名、修改……
#!/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()
Run Code Online (Sandbox Code Playgroud)