Я не думаю, что вы можете сделать это - не надежно и не так, как вы просите. Дело в том, что степень сжатия архива, вероятно, не будет равномерно распределена от головы к хвосту - алгоритм сжатия будет применяться к некоторым частям лучше, чем к другим. Вот только как это работает. И поэтому вы не можете учесть размер вашего разделения на размер сжатого файла.
Более того, gzip
просто не поддерживается сохранение исходного размера сжатых файлов размером более 4 ГБ - он не может с этим справиться. И поэтому вы не можете запросить архив, чтобы получить надежный размер - потому что он вас обманет.
4 строки - это довольно просто, правда. Дело в 4 файлах - я просто не знаю, как вы могли бы сделать это надежно и с равномерным распределением без предварительного извлечения архива, чтобы получить его несжатый размер. Я не думаю, что вы можете, потому что я пытался.
Однако, что вы можете сделать, это установить максимальный размер для разделенных выходных файлов и убедиться, что они всегда нарушаются при барьерах записи. Это вы можете легко сделать. Вот небольшой скрипт, который сделает это путем извлечения gzip
архива и передачи содержимого через несколько явных dd
конвейерных буферов с конкретными count=$rpt
аргументами, прежде чем передать его lz4
для распаковки / повторного сжатия каждого файла на лету. Я также добавил несколько маленьких tee
хитростей, чтобы напечатать последние четыре строки для каждого сегмента в stderr.
( IFS= n= c=$(((m=(k=1024)*k)/354))
b=bs=354xk bs=bs=64k
pigz -d </tmp/gz | dd i$bs o$b |
while read -r line _$((n+=1))
do printf \\n/tmp/lz4.$n\\n
{ { printf %s\\n "$line"
dd count=$c i$b o$bs
}| tee /dev/fd/3|lz4 -BD -9 >/tmp/lz4.$n
} 3>&1| tail -n4 |tee /dev/fd/2 |
wc -c;ls -lh /tmp/[gl]z*
done
)
Это будет продолжаться до тех пор, пока не будет обработан весь ввод. Он не пытается разделить его на некоторый процент - который он не может получить - но вместо этого он разделяет его на максимальное количество необработанных байтов за разделение. И в любом случае, большая часть вашей проблемы заключается в том, что вы не можете получить надежный размер для вашего архива, потому что он слишком большой - что бы вы ни делали, не делайте этого снова - сделайте сплиты менее 4 ГБ на кусок, так что , может быть. Этот маленький скрипт, по крайней мере, позволяет вам делать это без необходимости записывать несжатый байт на диск.
Ниже приведена более короткая версия, которая не включает в себя все элементы отчета:
( IFS= n= c=$((1024*1024/354))
pigz -d | dd ibs=64k obs=354xk |
while read -r line _$((n+=1))
do { printf %s\\n "$line"
dd count=$c obs=64k ibs=354xk
} | lz4 -BD -9 >/tmp/lz4.$n
done
) </tmp/gz
Он делает все то же самое, что и первый, в основном, ему просто нечего сказать об этом. Кроме того, там меньше беспорядка, так что легче понять, что происходит, может быть.
Все IFS=
дело в том, чтобы обрабатывать одну read
строку на одну итерацию. Мы read
один, потому что нам нужно, чтобы наш цикл заканчивался, когда ввод заканчивается. Это зависит от размера вашей записи - который, по вашему примеру, составляет 354 байта на. Я создал 4 + ГБ gzip
архив с некоторыми случайными данными, чтобы проверить его.
Случайные данные были получены следующим образом:
( mkfifo /tmp/q; q="$(echo '[1+dPd126!<c]sc33lcx'|dc)"
(tr '\0-\33\177-\377' "$q$q"|fold -b144 >/tmp/q)&
tr '\0-\377' '[A*60][C*60][G*60][N*16][T*]' | fold -b144 |
sed 'h;s/^\(.\{50\}\)\(.\{8\}\)/@N\1+\2\n/;P;s/.*/+/;H;x'|
paste "-d\n" - - - /tmp/q| dd bs=4k count=kx2k | gzip
) </dev/urandom >/tmp/gz 2>/dev/null
... но, может быть, вам не нужно беспокоиться об этом, так как у вас уже есть данные и все такое. Вернуться к решению ...
В основном pigz
- который, кажется, распаковывает немного быстрее, чем делает zcat
- передает несжатый поток и dd
буферы, которые выводят в блоки записи, размер которых определенно кратен 354 байтам. Цикл будет один раз в каждой итерации теста , что ввод еще прибывающего, который он будет потом на перед другим , называется для чтения размеров блоков конкретно на кратна 354-байт - для синхронизации с буферным процесса - в течение всего срока. Будет одно короткое чтение за каждую итерацию из-за начального - но это не имеет значения, потому что мы печатаем это в нашем процессе сбора - в любом случае.read
$line
printf
printf
lz4
dd
dd
read $line
lz4
Я настроил его так, что каждая итерация будет считывать примерно 1 ГБ несжатых данных и сжимать их в потоке примерно до 650 МБ или около того. lz4
гораздо быстрее, чем любой другой полезный метод сжатия - вот почему я выбрал его здесь, потому что я не люблю ждать. xz
возможно, будет гораздо лучше работать при фактическом сжатии. Но есть одна вещь lz4
, которая заключается в том, что он часто может распаковываться со скоростью, близкой к скорости ОЗУ, а это означает, что вы можете распаковывать lz4
архив так же быстро, как и в любом случае.
Большой делает несколько отчетов за одну итерацию. Оба dd
цикла напечатают отчет о количестве переданных необработанных байтов, скорости и т. Д. Большой цикл также будет печатать последние 4 строки ввода за цикл и количество байтов для него, а также ls
каталог, в который я записываю lz4
архивы. Вот несколько раундов вывода:
/tmp/lz4.1
2961+1 records in
16383+1 records out
1073713090 bytes (1.1 GB) copied, 169.838 s, 6.3 MB/s
@NTACGTANTTCATTGGNATGACGCGCGTTTATGNGAGGGCGTCCGGAANGC+TCTCTNCC
TACGTANTTCATTGGNATGACGCGCGTTTATGNGAGGGCGTCCGGAANGCTCTCTNCCGAGCTCAGTATGTTNNAAGTCCTGANGNGTNGCGCCTACCCGACCACAACCTCTACTCGGTTCCGCATGCATGCAACACATCGTCA
+
I`AgZgW*,`Gw=KKOU:W5dE1m=-"9W@[AG8;<P7P6,qxE!7P4##,Q@c7<nLmK_u+IL4Kz.Rl*+w^A5xHK?m_JBBhqaLK_,o;p,;QeEjb|">Spg`MO6M'wod?z9m.yLgj4kvR~+0:.X#(Bf
354
-rw-r--r-- 1 mikeserv mikeserv 4.7G Jun 16 08:58 /tmp/gz
-rw-r--r-- 1 mikeserv mikeserv 652M Jun 16 12:32 /tmp/lz4.1
/tmp/lz4.2
2961+1 records in
16383+1 records out
1073713090 bytes (1.1 GB) copied, 169.38 s, 6.3 MB/s
@NTTGTTGCCCTAACCANTCCTTGGGAACGCAATGGTGTGANCTGCCGGGAC+CTTTTGCT
TTGTTGCCCTAACCANTCCTTGGGAACGCAATGGTGTGANCTGCCGGGACCTTTTGCTGCCCTGGTACTTTTGTCTGACTGGGGGTGCCACTTGCAGNAGTAAAAGCNAGCTGGTTCAACNAATAAGGACNANTTNCACTGAAC
+
>G-{N~Q5Z5QwV??I^~?rT+S0$7Pw2y9MV^BBTBK%HK87(fz)HU/0^%JGk<<1--7+r3e%X6{c#w@aA6Q^DrdVI0^8+m92vc>RKgnUnMDcU:j!x6u^g<Go?p(HKG@$4"T8BWZ<z.Xi
354
-rw-r--r-- 1 mikeserv mikeserv 4.7G Jun 16 08:58 /tmp/gz
-rw-r--r-- 1 mikeserv mikeserv 652M Jun 16 12:32 /tmp/lz4.1
-rw-r--r-- 1 mikeserv mikeserv 652M Jun 16 12:35 /tmp/lz4.2
zcat file > /dev/null
?