You can actually use a dd pipe to accomplish this, without the performance penalty, without truncation or rounding errors, and with byte-level accuracy:
dd iflag=skip_bytes,count_bytes skip=1234 count=42 | dd oflag=seek_bytes conv=notrunc seek=12340 of=test.bin
On the left side, dd will skip the first 1234 bytes and read exactly 42 bytes. It will perform with efficient sector buffering and alignment. Exactly 42 bytes will be read at offset 1234 with no rounding errors. On the right side, dd will seek past exactly 12340 bytes on the output and write only the 42 bytes it receives from the pipe. It will perform with efficient sector buffering and alignment. In the pipeline, the two dd instances will send+receive data in sector-sized chunks for good performance, except for the last few bytes which are handled properly.
Note that there is no oflag for count_bytes, so this pipeline is required!
Here is an example attempting to count only 2 bytes, but without the pipeline. Notice that extra data is consumed on the input and written to the output:
$ printf aaa | dd oflag=seek_bytes conv=notrunc seek=0 count=2 | xxd
0+1 records in
0+1 records out
00000000: 6161 61 aaa
3 bytes copied, 0.000158916 s, 18.9 kB/s
dd
. You could always put a shell script wrapper around it if you don't like the interface.dd
is in the POSIX standard, which is a huge plus.status=noxfer
is not default and is broken and that I neediflag=fullblock
(omit in some script => broken data).bs=1
=> the whole pipeline is slow. For example I may want to dump video file starting from some exact frame. 2. "It takes some arithmetic" => not very suitable for oneliners and routine shell commands.dd conv=seek_bytes
will makeseek
work with byte precision.