Я хочу сжать много данных, распределенных по множеству подкаталогов, в архив. Я не могу просто использовать встроенные функции tar, потому что мне нужен сценарий Perl для работы как в среде Windows, так и в среде Linux. Я нашел модуль Archive::Tar
, но их документация выдает предупреждение:
Обратите внимание, что этот метод [
create_archive()
] не записываетon the fly
как бы; он по-прежнему считывает все файлы в память перед записью архива. Если это проблема, обратитесь к приведенным ниже часто задаваемым вопросам.
Из-за огромного размера моих данных я хочу писать «на лету». Но я не могу найти в FAQ полезной информации о записи файлов. Предлагают использовать итератор iter()
:
Возвращает функцию итератора, которая читает файл tar, не загружая его в память. Каждый раз, когда вызывается функция, она возвращает следующий файл в архиве.
my $next = Archive::Tar->iter( "example.tar.gz", 1, {filter => qr/\.pm$/} ); while( my $f = $next->() ) { print $f->name, "\n"; $f->extract or warn "Extraction failed"; # .... }
Но здесь обсуждается только чтение файлов, а не запись сжатого архива. Итак, у меня вопрос: как я могу взять каталог $dir
и рекурсивно добавить его в архив archive.tar.bz2
со сжатием bzip2 в удобной для памяти манере, то есть без предварительной загрузки всего дерева в память?
Я попытался создать свой собственный сценарий с предложениями в комментариях, используя Archive::Tar::Streamed
и IO::Compress::Bzip2
, но безуспешно.
use strict;
use warnings;
use Archive::Tar::Streamed;
use File::Spec qw(catfile);
use IO::Compress::Bzip2 qw(bzip2 $Bzip2Error);
my ($in_d, $out_tar, $out_bz2) = @ARGV;
open(my $out_fh,'>', $out_tar) or die "Couldn't create archive";
binmode $out_fh;
my $tar = Archive::Tar::Streamed->new($out_fh);
opendir(my $in_dh, $in_d) or die "Could not opendir '$in_d': $!";
while (my $in_f = readdir $in_dh) {
next unless ($in_f =~ /\.xml$/);
print STDOUT "Processing $in_f\r";
$in_f = File::Spec->catfile($in_d, $in_f);
$tar->add($in_f);
}
print STDOUT "\nBzip'ing $out_tar\r";
bzip2 $out_tar => $out_bz2
or die "Bzip2 failed: $Bzip2Error\n";
Очень быстро в моей системе заканчивается память. В моей текущей системе доступно 32 ГБ, но они почти сразу переполняются. Размер некоторых файлов в каталоге, который я пытаюсь добавить в архив, превышает 32 ГБ.
Поэтому мне интересно, должен ли каждый файл быть полностью прочитан в памяти даже в классе Streamed
перед добавлением в архив? Я предполагал, что сами файлы будут передаваться в буфере в архив, но, возможно, просто вместо того, чтобы сначала сохранять ВСЕ файлы в памяти, Streamed
позволяет полностью использовать только один файл в памяти, а затем добавлять его в архив один за другим. ?
tar
программу в Windows? В долгосрочной перспективе может быть проще. - person melpomene   schedule 30.07.2017tar
) и Windows (не встроенный)? (tar
ing не является автономным и является частью более крупного Perl-скрипта.) - person Bram Vanroy   schedule 30.07.2017Archive::Tar::Streamed
, как описано в вопрос, с которым мелпомена связана? Вопреки принятому ответу, для него не требуетсяtar
служебная программа командной строки, и это должно подойти в ваших системах Windows. В документации говорится, что он также нацелен на переносимость и доступность на платформах без собственного tar. - person Borodin   schedule 30.07.2017tar
, в любом случае используя Archive :: Tar? Но разве это не означает, что всеtar
(возможно, сотни гигабайт) должны быть прочитаны в памяти? - person Bram Vanroy   schedule 30.07.2017Streamed
позволяет полностью разместить только один файл в памяти, а затем добавлять его в архив по одному? Основное отличие отArchive::Tar
в том, что tar-файл создается постепенно на диске, а не в памяти. Добавление файла или списка файлов в архив потребует, чтобы все данные этих файлов находились в памяти, какой бы модуль ни использовался. Это можно свести к минимуму, добавляя только один файл за раз. Включают ли ваши данные какие-либо отдельные файлы размером в несколько гигабайт? Я написал короткое решение и опубликую его завтра, если у вас нет файлов, которые не умещаются в памяти. - person Borodin   schedule 30.07.2017Archive::Tar
, который направляет на вывод отдельные файлы, а также весь архив. Это не должно быть сложно. Между тем, да, вы можете использоватьsystem
или обратные кавычки. Windows не поставляется с архиватором командной строки tar или bzip2, но с GnuWin i > предоставляет и то, и другое. - person Borodin   schedule 30.07.2017