我认为您无法做到这一点-不可靠,也不是您要求的方式。事实是,压缩文件的压缩率可能不会从头到尾均匀分布-压缩算法将在某些部分比其他部分更好地应用。这就是它的工作原理。因此,您不能将压缩文件的大小作为分割因素。
而且,gzip
不支持存储大于4GB的压缩文件的原始大小-它无法处理。因此,您无法查询存档以获取可靠的大小-因为它会使您蒙昧。
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
)
这将一直继续下去,直到处理完所有输入。它不会尝试按一定百分比进行拆分(无法获得),而是按每次拆分的最大原始字节数进行拆分。而且无论如何,问题的很大一部分是您无法在归档文件中获得可靠的大小,因为它太大了-无论您做什么,都不要再这样做-使拆分的碎片小于4GB , 也许。至少,这个小脚本使您无需写未压缩的字节到磁盘即可执行此操作。
这是精简要点的简短版本-并非所有报告内容都包括在内:
( 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
为了测试它,我创建了一个4GB的存档,其中包含一些随机数据。
随机数据是通过以下方式获得的:
( 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字节的倍数。该循环将read
在$line
每次迭代中测试一次输入是否仍然到达,printf
然后printf
在调用lz4
另一个循环之前dd
读取该块,以读取特定大小为354字节倍数的块,以与缓冲dd
过程保持同步。每次迭代都会有一个简短的读取,这是因为初始的read $line
-没关系,因为lz4
无论如何,我们都在收集器过程中打印它。
我将其设置为每次迭代将读取大约1gb的未压缩数据,并将其流内压缩到大约650Mb左右。lz4
比任何其他有用的压缩方法都快得多-这就是我在这里选择它的原因,因为我不想等待。xz
不过,实际压缩可能会做得更好。lz4
不过,有一点是,它通常可以接近RAM的速度解压缩-这意味着很多时候,您可以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
需要多长时间?