Я не думаю, що ти можеш це зробити - не надійно, і не так, як ти просиш. Справа в тому, що коефіцієнт стиснення архіву, ймовірно, не буде рівномірно розподілений від голови до хвоста - алгоритм стиснення буде застосовуватися краще до деяких частин, ніж до інших. Ось так воно і працює. Таким чином, ви не можете розподілити коефіцієнт поділу на розмір стисненого файлу.
Більше того, gzip
просто не підтримує збереження оригінального розміру стислих файлів розміром більше 4 Гб - він не може впоратися з цим. І тому ви не можете запитувати архів, щоб отримати надійний розмір - адже він вас обдурить.
4-річна річ - це дуже просто, насправді. 4-файльна річ - я просто не знаю, як ви могли це зробити надійно і рівномірним розподілом без попереднього вилучення архіву, щоб отримати його нестиснений розмір. Я не думаю, що ти можеш, тому що я намагався.
Однак, що ви можете зробити, встановіть максимальний розмір для розділених вихідних файлів і переконайтеся, що вони завжди порушені на межі запису. Це ви легко можете зробити. Ось невеликий сценарій, який зробить це, витягнувши gzip
архів і прокачивши вміст через декілька явних dd
буферних буферів з конкретними count=$rpt
аргументами, перед тим як пропустити його lz4
для декомпресії / повторного повторного копіювання кожного файлу на льоту. Я також наклав кілька невеликих tee
трюків, щоб надрукувати останні чотири рядки для кожного сегмента, щоб також було складніше.
( 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 байти на кожен. Я створив gzip
архів 4 + gb з деякими випадковими даними, щоб перевірити його.
Випадкові дані отримані таким чином:
( 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
?