これはあなたがこれを行うことができる方法です:
i=$(((t=19876543212)-(h=12345678901)))
{ dd count=0 skip=1 bs="$h"
dd count="$((i/(b=64*1024)-1))" bs="$b"
dd count=1 bs="$((i%b))"
} <infile >outfile
本当に必要なのはこれだけです-それ以上は必要ありません。まず第一にdd count=0 skip=1 bs=$block_size1
なりlseek()
、実質的に瞬時に通常のファイル入力の上。データを見逃したり、他の真実が伝えられたりする可能性はありません。目的の開始位置に直接シークできます。ファイル記述子はシェルによって所有されており、dd
「」は単にそれを継承しているだけなので、それらはカーソル位置に影響を与えるので、それを段階的に実行できます。それは本当に非常に簡単です-そして、タスクより適した標準ツールはありませんdd
。
多くの場合理想的な64kブロックサイズを使用します。一般的な考えに反して、ブロックサイズが大きいとdd
作業が速くなりません。一方で、小さなバッファも良くありません。dd
システムコールで時刻を同期して、データをメモリにコピーしてから再び出力するのを待つ必要がないようにするだけでなく、システムコールを待つ必要もありません。そのため、次のread()
レコードが最後のレコードを待つ必要がないように十分な時間をかける必要がありますが、必要以上に大きなサイズでバッファリングするほどには時間がかかりません。
したがって、最初dd
は開始位置にスキップします。それには時間がかかりません。その時点で気に入った他のプログラムを呼び出してそのstdinを読み取ると、目的のバイトオフセットで直接読み取りを開始できます。別のdd
ものを呼び出して、((interval / blocksize) -1)
countブロックを標準出力に読み取ります。
最後に必要なことは、前の除算操作のモジュラス(ある場合)をコピーすることです。それだけです。
ところで、人々が証拠なしに自分の顔に事実を述べるとき、それを信じないでください。はい、dd
短い読み取りを行うことは可能です(ただし、健全なブロックデバイスから読み取る場合はこのようなことはできません-つまり名前)。このようなことはdd
、ブロックデバイス以外から読み取られたストリームを正しくバッファリングしない場合にのみ可能です。例えば:
cat data | dd bs="$num" ### incorrect
cat data | dd ibs="$PIPE_MAX" obs="$buf_size" ### correct
どちらの場合も、すべてのデータがdd
コピーされます。最初のケースでは、それは可能である(とそういえ)の出力ブロックのいくつかのことをするので意志アウトコピーが等しい「$ numは」ビットバイトがspec'dされるだけで、すべてで何かをバッファリングするためのバッファは、具体的にそのコマンド-上要求されたときライン。の目的はリアルタイムI / O であるため、最大ブロックサイズを表します。cat
dd
dd
bs=
dd
2番目の例では、出力ブロックサイズを明示的に指定し、dd
完全な書き込みが行われるまで読み取りをバッファリングします。count=
どちらが入力ブロックに基づいているかには影響しませんが、そのためには別のものが必要dd
です。そうでなければあなたに与えられたいかなる誤報も無視されるべきです。
bs=1M iflag=skip_bytes,count_bytes