No creo que puedas hacer esto, no de manera confiable, y no de la manera que lo pides. La cuestión es que la relación de compresión del archivo probablemente no se distribuirá de manera uniforme de la cabeza a la cola: el algoritmo de compresión se aplicará mejor a algunas partes que a otras. Así es como funciona. Por lo tanto, no puede factorizar su división en el tamaño del archivo comprimido.
Además, gzip
simplemente no admite el almacenamiento del tamaño original de archivos comprimidos de más de 4 gbs de tamaño, no puede manejarlo. Por lo tanto, no puede consultar el archivo para obtener un tamaño confiable, porque lo engañará.
Lo de 4 líneas: eso es bastante fácil, de verdad. Lo de los 4 archivos: simplemente no sé cómo podría hacerlo de manera confiable y con una distribución uniforme sin extraer primero el archivo para obtener su tamaño sin comprimir. No creo que puedas porque lo intenté.
Sin embargo, lo que puede hacer es establecer un tamaño máximo para los archivos de salida divididos y asegurarse de que siempre se rompan en las barreras de registro. Eso puedes hacer fácilmente. Aquí hay una pequeña secuencia de comandos que lo hará extrayendo el gzip
archivo y canalizando el contenido a través de algunos dd
buffers de tubería explícitos con count=$rpt
argumentos específicos , antes de pasarlo lz4
para descomprimir / recomprimir cada archivo sobre la marcha. También agregué algunos pequeños tee
trucos de tubería para imprimir las últimas cuatro líneas para cada segmento para stderr también.
( 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
)
Eso continuará hasta que haya manejado todas las entradas. No intenta dividirlo en algún porcentaje, que no puede obtener, sino que lo divide por un recuento máximo de bytes sin procesar por división. Y de todos modos, una gran parte de su problema es que no puede obtener un tamaño confiable en su archivo porque es demasiado grande, haga lo que haga, no vuelva a hacer eso, haga que las divisiones de menos de 4 gbs por pieza sean redondas. , tal vez. Este pequeño script, al menos, le permite hacer esto sin tener que escribir un byte sin comprimir en el disco.
Aquí hay una versión más corta despojada de lo esencial: no agrega todas las cosas del informe:
( 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
Hace todo lo mismo que el primero, principalmente, simplemente no tiene mucho que decir al respecto. Además, hay menos desorden, por lo que es más fácil ver lo que está sucediendo, tal vez.
La IFS=
cuestión es solo manejar una read
línea por iteración. Somos read
uno porque necesitamos que nuestro ciclo finalice cuando finaliza la entrada. Esto depende del tamaño de su registro , que, según su ejemplo, es de 354 bytes por. Creé un gzip
archivo de 4 + gb con algunos datos aleatorios para probarlo.
Los datos aleatorios se obtuvieron de esta manera:
( 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
... pero tal vez no tenga que preocuparse tanto por eso, ya que ya tiene los datos y todo. De vuelta a la solución ...
Básicamente pigz
, que parece descomprimirse un poco más rápido que lo hace zcat
, canaliza el flujo sin comprimir y dd
almacena en búfer la salida en bloques de escritura de un tamaño específico en un múltiplo de 354 bytes. El bucle read
una $line
vez cada iteración a la prueba de que la entrada todavía está llegando, que será printf
después printf
en lz4
antes de que otro dd
se llama para leer bloques de tamaño específicamente a un múltiplo de 354 bytes - para sincronizar con el almacenamiento en búfer dd
proceso - para la duración. Habrá una breve lectura por iteración debido a la inicial read $line
, pero eso no importa, porque de lz4
todos modos estamos imprimiendo eso en nuestro proceso de recopilación.
Lo configuré para que cada iteración lea aproximadamente 1 gb de datos sin comprimir y comprima ese in-stream a alrededor de 650Mb más o menos. lz4
es mucho más rápido que casi cualquier otro método de compresión útil, razón por la cual lo elegí aquí porque no me gusta esperar. xz
Sin embargo, probablemente haría un trabajo mucho mejor en la compresión real. Sin lz4
embargo, una cosa es que a menudo puede descomprimirse a velocidades cercanas a la RAM, lo que significa que muchas veces puede descomprimir un lz4
archivo tan rápido como podría escribirlo en la memoria de todos modos.
El grande hace algunos informes por iteración. Ambos bucles imprimirán dd
el informe sobre la cantidad de bytes sin procesar transferidos y la velocidad, etc. El bucle grande también imprimirá las últimas 4 líneas de entrada por ciclo, y un recuento de bytes para el mismo, seguido de uno ls
del directorio en el que escribo los lz4
archivos. Aquí hay un par de rondas de salida:
/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
?