我有一个 .7z 文件,其中包含多个目录中的约 360,000 张图片。我想将其转换为 .tar,以便可以在另一台计算机上打开它。有没有比将其提取到文件并再次压缩更好的方法?是否可以直接进行转换?
答案1
.7z
档案就是经过某种算法压缩的档案,.tar
档案就是档案。
它们的范围不同,在大多数情况下,转换需要可选的解压缩,然后始终提取源档案。即使档案.7z
不使用任何压缩,它仍然需要提取。
话虽如此,如果你想要立即解压/提取/重新归档源存档,答案是你不能,至少不能使用 Ubuntu 的默认工具,因为tar
无法读取stdin
,因此您不能使用管道7z
和tar
。无论如何,使用单个命令即可轻松实现所有操作的自动化:
mkdir tmp && 7z x <path_to_source_archive> -otmp && tar cf archive.tar tmp && rm -rf tmp
* <path_to_archive> = 源.7z
档案的路径
此外,将源档案的文件写入磁盘以及读取提取的文件以便 [解压缩]/提取/重新归档源档案(分两步)所需的时间也是整个任务的瓶颈大多(虽然不只是)因为潜在磁盘的 I/O 速度较低,所以部分解决方案是将临时文件存储到 ramdisk 中,以几乎消除整体瓶颈:
- 为 ramdisk 的文件系统创建挂载点:
sudo mkdir /mnt/tmpfs
- 挂载 ramdisk 的文件系统:
sudo mount -t tmpfs -o size=<tmpfs_size> tmpfs /mnt/ramdisk
* <tmpfs_size> = 文件系统的大小(以字节为单位) * 10 3 (1、1K、1M、1G、...) - 运行
mkdir /mnt/tmpfs/tmp && 7z x <path_to_source_archive> -o/mnt/tmpfs/tmp && tar cf archive.tar /mnt/tmpfs/tmp && rm -rf /mnt/tmpfs/tmp
* <path_to_archive> = 源.7z
档案的路径 - 卸载 ramdisk 的文件系统:
sudo umount
- 删除 ramdisk 文件系统的挂载点:
sudo rmdir /mnt/tmpfs
答案2
编写一些代码来完成这项工作并不难。下面是一个示例 Perl 脚本(需要模块档案::Libarchive::XS)。
#!/usr/bin/perl
use strict;
use warnings;
use Archive::Libarchive::XS qw(:all);
die "Usage: $0 in.7z out.tar" unless @ARGV == 2;
my ($infile, $outfile) = @ARGV;
my $in = archive_read_new();
archive_read_support_filter_none($in);
archive_read_support_format_7zip($in);
archive_read_open_filename($in, $infile, 10240) == ARCHIVE_OK
or die "Error opening $infile: ", archive_error_string($in);
my $out = archive_write_new();
archive_write_set_format_ustar($out);
archive_write_open_filename($out, $outfile) == ARCHIVE_OK
or die "Error opening $outfile: ", archive_error_string($out);
while (archive_read_next_header($in, my $entry) == ARCHIVE_OK) {
archive_write_header($out, $entry) == ARCHIVE_OK
or die archive_error_string($out);
while (1) {
my $size = archive_read_data($in, my $buff, 65536);
die archive_error_string($in) if $size < 0;
last if $size == 0;
archive_write_data($out, $buff) >= 0
or die archive_error_string($out);
}
}
archive_read_free($in);
archive_write_close($out);
archive_write_free($out);
如果您想要 tar.gz / tar.bz2 / tar.xz 存档,请在该行后添加该行archive_write_add_filter_gzip($out);
或archive_write_add_filter_bzip2($out);
或。archive_tar_add_filter_xz($out);
archive_write_set_format
这不使用临时磁盘空间(仅占用输出 tar 文件的空间)和很少的 RAM(对于 perl 来说只有几 MB,但它一次处理一个块的文件,因此即使您的文件大于 RAM 也没有问题)。