In the dd
command, we can use skip
to skip n byte in a file. From nth byte to end of file is copied. But I want to copy binary data from 1228 to 1331 only.
How do I achieve this with dd
on Linux?

- 242,166

- 151
- 2
- 8
3 Answers
Use the count
to specify the number of bytes to copy. Use the shell to do the calculation. Use ibs=1
to set the input block size to 1, so the skip
and count
are specified in bytes.
dd ibs=1 skip=1228 count=$((1331-1228+1))
As 1228 and 1331-1228+1 are both multiples of 4 it would be possible to set the input block size to 4, which would make things more efficient but unless this was going to be used an enormous number of times the optimization will be lost in the noise. Other things like pre-calculating the result of 1331-1228+1
should be done first.
dd ibs=4 skip=$((1228/4)) count=$(((1331-1228+1)/4))

- 17,920
-
Whats ibs parameter ? – Ashish Pawar Sep 25 '19 at 11:20
-
@AashishPawar answer expanded to explain a little about ibs. – icarus Sep 25 '19 at 22:01
There's no reason to use dd
at all. A simple head
and tail
combination is enough (requires GNU tools) :
head -c 1331 file | tail -c $((1331-1228+1))

- 242,166
-
-
-
-
The OP is on linux, but you edit the question to delete the linux tag, but your answer depends on common linux extensions??? Perhaps you should revert your edit. – icarus Sep 25 '19 at 11:18
-
@icarus argh, you're quite right, sorry! I removed the tag because tags shouldn't be used to specify the OS (the
linux
tag would be next to useless in this site since the vast majority of questions are from people running Linux), but I stupidly forgot to add it to the question! Thanks for the reminder. – terdon Sep 25 '19 at 14:44
just finished an common script dd-file-range.sh: dd-file-range.sh
used to copy of a byte range from one file to another.
like syscall copy_file_range(2) on linux kernel-5.3 or FreeBSD-13
see also: linux copye_file_range() and FreeBSD copy_file_range()
and could also use the xfs_io->copy_range sub-command in newer linux distributions instead dd-file-range.sh
Usage:
$ dd-file-range.sh
Usage: dd-file-range.sh <ifile[:skip_offset[:len]]> [ofile[:seek_offset]] [-bs=BSIZE] [-sep=<seperator>] [-log=<0|1|2>]
#Comment: if 'skip_offset' start with '['; trate it as 'start' #((start=skip_offset+1))
#Comment: if 'len' has a suffix ']'; trate it as 'end' #((end=skip_offset+len))
#Comment: e.g: ifile:5:5 <=is equivalent to=> ifile:[6:10]
Examples:
dd-file-range.sh ifile:8192:512 ofile
dd-file-range.sh ifile::4096 ofile:1024
dd-file-range.sh ifile:4 #output to stdout
dd-file-range.sh <(cat):4 ofile #read from stdin
dd-file-range.sh ifile::4 ifile:10 #copy data within same file
for the original question, we can use dd-file-range.sh like:
$ dd-file-range.sh kiss-vm:$((1228-1)):$((1331-1228+1))
$ #or simple
$ dd-file-range.sh kiss-vm:[1228:1331]
performance test with different bs:
$ ls -lh kiss-vm.gif
-rw-r--r-- 1 yjh fs-qe 4.0M May 12 2021 kiss-vm.gif
$ time dd-file-range.sh kiss-vm.gif:1981 b:1981 -ver=old -bs=$((128*1024))
real 0m0.023s
user 0m0.005s
sys 0m0.026s
$ time dd-file-range.sh kiss-vm.gif:1981 b:1981 -ver=old -bs=$((64*1024))
real 0m0.023s
user 0m0.007s
sys 0m0.022s
$ time dd-file-range.sh kiss-vm.gif:1981 b:1981 -ver=old #default BS == $((16*1024))
real 0m0.022s
user 0m0.003s
sys 0m0.025s
$ time dd-file-range.sh kiss-vm.gif:1981 b:1981 -ver=old -bs=$((8*1024))
real 0m0.022s
user 0m0.005s
sys 0m0.023s
$ time dd-file-range.sh kiss-vm.gif:1981 b:1981 -ver=old -bs=$((4*1024))
real 0m0.023s
user 0m0.008s
sys 0m0.022s
$ time dd-file-range.sh kiss-vm.gif:1981 b:1981 -ver=old -bs=1024
real 0m0.024s
user 0m0.005s
sys 0m0.028s
$ time dd-file-range.sh kiss-vm.gif:1981 b:1981 -ver=old -bs=512
real 0m0.039s
user 0m0.006s
sys 0m0.048s
$ time dd-file-range.sh kiss-vm.gif:1981 b:1981 -ver=old -bs=256
real 0m0.037s
user 0m0.010s
sys 0m0.044s
$ time dd-file-range.sh kiss-vm.gif:1981 b:1981 -ver=old -bs=128
real 0m0.046s
user 0m0.012s
sys 0m0.057s
$ time dd-file-range.sh kiss-vm.gif:1981 b:1981 -ver=old -bs=64
real 0m0.072s
user 0m0.011s
sys 0m0.102s
$ time dd-file-range.sh kiss-vm.gif:1981 b:1981 -ver=old -bs=32
real 0m0.129s
user 0m0.014s
sys 0m0.199s
$ time dd-file-range.sh kiss-vm.gif:1981 b:1981 -ver=old -bs=16
real 0m0.275s
user 0m0.049s
sys 0m0.425s
$ time dd-file-range.sh kiss-vm.gif:1981 b:1981 -ver=old -bs=8
real 0m0.460s
user 0m0.077s
sys 0m0.707s
$ time dd-file-range.sh kiss-vm.gif:1981 b:1981 -ver=old -bs=4
real 0m1.278s
user 0m0.208s
sys 0m2.082s
$ time dd-file-range.sh kiss-vm.gif:1981 b:1981 -ver=old -bs=2
real 0m1.841s
user 0m0.294s
sys 0m2.846s
$ time dd-file-range.sh kiss-vm.gif:1981 b:1981 -ver=old -bs=1
real 0m3.924s
user 0m0.610s
sys 0m6.227s

- 1
-
1What does this program do? There's nothing even on the GitHub link that explains what it does or why someone should need to use it – Chris Davies Mar 11 '22 at 07:23
-
Despite the recent edit, you still don't explain what it does or why someone should need to use it – Chris Davies Mar 14 '22 at 08:17
-
thanks @roaima for your patience, edit/update again :) added more instructions and updated the script. – Jianhong Mar 15 '22 at 06:54
-
This shell script is just an overly complicated bash shell script wrapper around
dd
– fpmurphy Mar 15 '22 at 07:26 -