Não é muito difícil escrever algo para fazer o trabalho. Aqui está um exemplo de script Perl (requer o módulo Archive :: 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);
Se você quiser um arquivo tar.gz / tar.bz2 / tar.xz, adicione a linha archive_write_add_filter_gzip($out);
ou archive_write_add_filter_bzip2($out);
ou archive_tar_add_filter_xz($out);
após a linha archive_write_set_format
.
Isso não usa espaço em disco temporário (apenas o espaço para o arquivo tar de saída) e muito pouca RAM (apenas alguns MB para perl, mas funciona com os arquivos um bloco por vez, portanto, não é um problema se os arquivos são maiores que sua RAM).