我想从这里下载一个大 (199GB) .tar.gz 文件的一部分。首先,我使用以下命令列出 .tar.gz 文件中的所有文件:
wget -qO- https://www.cs.cornell.edu/projects/megadepth/dataset/Megadepth_v1/MegaDepth_v1.tar.gz | tar -tz
接下来,我尝试使用以下命令下载 .tar.gz 中文件夹的内容:
wget -qO- https://www.cs.cornell.edu/projects/megadepth/dataset/Megadepth_v1/MegaDepth_v1.tar.gz | tar -xz phoenix/S6/zl548/MegaDepth_v1/0000
但是,这需要很长时间,因为该tar
命令会深度优先搜索并递归地搜索下面的每个文件夹phoenix/S6/zl548/MegaDepth_v1
。我只对文件夹的内容感兴趣phoenix/S6/zl548/MegaDepth_v1/0000
。有没有办法在不搜索其他文件夹的子文件夹的情况下下载该文件夹的内容,例如
phoenix/S6/zl548/MegaDepth_v1/0162
phoenix/S6/zl548/MegaDepth_v1/0001
phoenix/S6/zl548/MegaDepth_v1/0132
换句话说,有没有更快的方法来下载文件夹的内容phoenix/S6/zl548/MegaDepth_v1/0000
?
上述命令的一些参考:
tar
写入文件头,然后是文件内容,然后是下一个文件头,下一个文件内容,依此类推。没有与条目关联的顺序,您可以提出的唯一优化是跳过文件的内容,以获取下一个标题,直接查找它。为此,您需要有一个可搜索的文件。
但是你的文件
.gz
是压缩的,所以你没有可靠的方法可以跳到下一个条目,这意味着你必须阅读(下载)整个文件才能获取内容。这就是答案:不,您无法避免读取/下载整个文件。所以,既然无论如何你都必须完全下载它,你最好只下载一次,然后在本地文件系统中解决所有问题。
嗯,实际上并没有。它根本不搜索 ,而只是通读存档,查看它遇到的每个文件,看看它们是否匹配它想要的。(您确实得到了深度优先的行为,因为这是遍历目录树的自然顺序,因此也是将文件添加到存档中的顺序。)
这是因为 tar 档案没有索引,它们是不可搜索的。名称“tar”代表“磁带存档”,使用磁带的通常模式是仅读取或写入单个流,无需查找。该格式是针对该上下文制作的,对于您的用例可能不是最好的。
我找不到很好的引用,但在网站和Wikipedia上的一些 答案中提到了它。
每次执行时
wget
,您都在尝试下载整个 tar 文件!您可能已经多次下载“初始内容”,并通过将输出发送到标准输出将其丢弃!相反,“更快”的方法是将它下载一次到当前目录中的 ./MegaDepth_v1.tar.gz 并在那里解压。
获得必要的文件后,您可以删除下载的 tar 文件。
更新:原始文件的大小似乎约为 200 GB。下载本身将占用大量时间和空间。提取将占用额外的时间。没有胜利,在这种情况下!
您可能必须联系 MegaDepth 团队并要求他们提供单独的目录访问权限,否则会很慢。
在这里,
wget
不能跳过不需要的内容,并且总是从头到尾下载整个 tar 文件。此外,(如用户 ilkkach 的回答中所述)tar
不能跳过(或查找)标准输出流。分析
我同意其他答案,说没有办法
tar
寻找压缩档案。要找到您要查找的文件,该工具需要从头开始处理存档,而不是跳过任何内容。但是,使用 GNU
tar
,您不一定需要将其处理到最后。创建存档时考虑这种情况:(来源)
这意味着,在提取特定文件时,
tar
即使在提取文件之后也会继续处理存档,因为存档中稍后可能会有另一个副本。但是之后:
(同上)
如果您确定您要查找的文件在存档中恰好出现一次,请使用
tar --occurrence
并tar
在提取文件后停止。然后您wget
将因 中止SIGPIPE
,它不会徒劳地下载存档的其余部分。用处有限
请注意,这在您的确切情况下并不是很有用,因为
phoenix/S6/zl548/MegaDepth_v1/0000
它是一个目录(对吗?)。--occurrence
使用,提取目录时tar
不会提前停止,除非遇到目录本身的另一个条目。phoenix/S6/zl548/MegaDepth_v1/0000/foo
原因是:档案的最后总是有一个独特的。在tar
结束之前,无法确定包含所有内容的目录是否完整。尽管如此,如果您在一个或几个非目录之后,如果您知道路径并且如果您知道存档中每个目录都只有一个实例,那么
--occurrence
您可以根据需要下载尽可能少的存档。如果您很幸运并且文件恰好位于存档的开头附近,那么--occurrence
将会产生重大影响。可能这个答案对你没有多大帮助。它适用于可以提供非目录列表的用户。
除非…
如果您保存了
wget -qO- … | tar -tz
(当您很可能下载并处理了整个存档并将其丢弃时)的输出,您现在可以提供非目录列表(可能使用--files-from=
or--verbatim-files-from
;如果列表太长,则特别有用对于单个命令行)。在这种情况下--occurrence
可能对你有用。此外,保存的输出tar -t
将允许您确认您所追求的每个非目录在存档中只出现一次,因此您知道--occurrence
不会让您错过更新的版本。以上假设
MegaDepth_v1.tar.gz
在服务器上没有改变。通常(如果存档可能已更改)您保存的输出tar -t
可能不再有效。假设您可以创建要提取的非目录列表。该列表不能明确指定任何目录,否则
--occurrence
对您没有帮助。仍然tar
会创建必要的目录,但只是为了在其中放置非目录,而不是因为它会真正从存档中提取目录。换句话说:目录本身的存档成员无关紧要。这意味着将创建目录,但诸如此类的选项--preserve-permissions
将不适用于它们。概念证明
我使用了您的第一个命令(带有 的命令
tar -t
),发现它phoenix/S6/zl548/MegaDepth_v1/0162/dense0/depths/16384199365_2b34b42cf4_b.h5
是档案开头附近的一个非目录。这个管道:提取文件并继续(我可以Ctrl+ c);但是这个:
提取文件并自动终止。