从.tar-archive有效地提取单个文件

MID*_*E11 5 python

我有一个.tgz大小为2GB 的文件.

我想.txt从.tgz文件中只提取一个大小为2KB的文件.

我有以下代码:

import tarfile
from contextlib import closing

with closing(tarfile.open("myfile.tgz")) as tar:
    subdir_and_files = [
        tarinfo for tarinfo in tar.getmembers()
        if tarinfo.name.startswith("myfile/first/second/text.txt")
        ]
    print subdir_and_files
    tar.extractall(members=subdir_and_files)
Run Code Online (Sandbox Code Playgroud)

问题是我得到提取的文件至少需要一分钟.似乎extractall提取所有文件,但只保存我问的那个.

有没有更有效的方法来实现它?

Яро*_*лин 0

不。

tar 格式不太适合快速提取单个文件。在大多数情况下,这种情况会加剧,因为 tar 文件通常位于压缩流中。我建议7z。

是的,有点。

如果您知道只有一个具有该名称的文件,或者您只需要一个文件,则可以在第一次点击后中止提取过程。

例如

彻底扫描该东西。

$ time tar tf /var/log/apache2/old/2016.tar.xz 
2016/
2016/access.log-20161023
2016/access.log-20160724
2016/ssl_access.log-20160711
2016/error.log-20160815
(...)
2016/error.log-20160918
2016/ssl_request.log-20160814
2016/access.log-20161017
2016/access.log-20160516
time: Real 0m1.5s  User 0m1.4s  System 0m0.2s
Run Code Online (Sandbox Code Playgroud)

从记忆中扫描这个东西

$ time tar tf /var/log/apache2/old/2016.tar.xz  > /dev/null 
time: Real 0m1.3s  User 0m1.2s  System 0m0.2s
Run Code Online (Sandbox Code Playgroud)

第一个文件后中止

$ time tar tf /var/log/apache2/old/2016.tar.xz  | head -n1 
2016/
time: Real 0m0.0s  User 0m0.0s  System 0m0.0s
Run Code Online (Sandbox Code Playgroud)

三个文件后中止

$ time tar tf /var/log/apache2/old/2016.tar.xz  | head -n3 
2016/
2016/access.log-20161023
2016/access.log-20160724
time: Real 0m0.0s  User 0m0.0s  System 0m0.0s
Run Code Online (Sandbox Code Playgroud)

在“中间”的某个文件后中止

$ time tar xf /var/log/apache2/old/2016.tar.xz  2016/access.log-20160724  | head -n1 
time: Real 0m0.9s  User 0m0.9s  System 0m0.1s
Run Code Online (Sandbox Code Playgroud)

在“底部”的某个文件后中止

$ time tar xf /var/log/apache2/old/2016.tar.xz  2016/access.log-20160516  | head -n1 
time: Real 0m1.1s  User 0m1.1s  System 0m0.2s
Run Code Online (Sandbox Code Playgroud)

我在这里向您展示,如果您通过在第一行(head -n1)之后退出来终止 GNU tar 的输出管道(标准输出),那么 tar 进程也会终止。

您可以看到,读取整个存档比在接近存档“底部”的某个文件后中止花费更多时间。您还可以看到,在遇到顶部文件后中止读取所需的时间明显减少。

如果我可以决定存档的格式,我就不会这样做。


苏...

与其使用Python人非常喜欢的列表理解方式,不如迭代tar.getmembers()(或者在该库中一次给你一个文件的任何方式)并在遇到所需结果时中断,而不是将所有文件展开到列表中。