私はあなたがこれを行うことができるとは思いません-確実ではなく、あなたが尋ねる方法ではありません。問題は、アーカイブの圧縮率がおそらく先頭から末尾に均等に分散されないことです-圧縮アルゴリズムは他の部分よりもある部分によく適用されます。それはまさにそれが機能する方法です。そのため、圧縮ファイルのサイズで分割を考慮することはできません。
そのうえ、 gzip
GBを超えるサイズの圧縮ファイルの元のサイズの保存をサポートしていないため、処理できません。そして、信頼できるサイズを取得するためにアーカイブをクエリすることはできません-だまされてしまうからです。
4行のこと-それは本当に簡単です。4ファイルのこと-アーカイブを解凍して圧縮されていないサイズを取得せずに、均等なディストリビューションで確実にそれを行う方法を知りません。私がやってみたので、あなたができるとは思いません。
ただし、できることは、分割された出力ファイルの最大サイズを設定し、それらが常にレコードの障壁で壊れることを確認することです。簡単にできること。次の小さなスクリプトは、gzip
アーカイブを抽出し、dd
特定のcount=$rpt
引数を持ついくつかの明示的なパイプバッファーを介してコンテンツをパイプ処理してlz4
から、各ファイルをその場で解凍/再圧縮するために渡すスクリプトです。またtee
、各セグメントの最後の4行を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
1ので、我々は、入力が終了終了する私たちのループを必要としています。これは、レコードサイズによって異なります。たとえば、例では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バイト-バッファと同期する期間の間-プロセス。イニシャルのため、反復ごとに1回の短い読み取りがありますが、それは重要ではありません。read
$line
printf
printf
lz4
dd
dd
read $line
lz4
ますが、コレクタープロセス-とにかくん。
各反復で約1GBの非圧縮データを読み取り、そのインストリームを約650Mb程度に圧縮するように設定しました。lz4
他のほとんどの有用な圧縮方法よりもはるかに高速です。これが、私が待つのが好きではないためにここで選択した理由です。xz
おそらく、実際の圧縮でははるかに良い仕事をするでしょう。lz4
ただし、の1つは、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
かかりますか?