2

Man dd:

dd - convert and copy a file

I'm leaning to use dd. Strangely after copying 1 byte text file becomes much smaller:

$ block_size=1; device_to_edit=/media/ramdrive/a; device_from=/media/ramdrive/b; echo "aaaaaaaaaa">$device_to_edit; echo "bbbbbbbbbb">$device_from; cat $device_to_edit; cat $device_from; dd if=$device_from of=$device_to_edit count=1 seek=2 skip=2 bs=$block_size; cat $device_to_edit
aaaaaaaaaa
bbbbbbbbbb
1+0 records in
1+0 records out
1 byte copied, 0,000156688 s, 6,4 kB/s
aab

It said 1 byte copied, why end of file is gone?

Added:

As comment suggested, conv=notrunc fixes it. But from man:

conv=CONVS convert the file as per the comma separated symbol list

I did not want to convert a file. When reading about copying block devices, I have not seen this operand. Is it always needed when not all file (e.g. one 512 bytes block in /dev/sdb: USB disk) is changed?

2
  • 1
    block_size=1; dd count=1 bs=$block_size; You're asking it to copy just one byte. If you want to copy some bytes to the middle of the file without affecting the rest, add conv=notrunc.
    – ilkkachu
    Oct 29, 2021 at 12:03
  • @ilkkachu, thank you. Could you please have a look at "added"? Oct 29, 2021 at 12:15

2 Answers 2

4

What you're doing is this:

block_size=1; 
dd ... count=1 seek=2 skip=2 bs=$block_size; 

you're asking dd to copy just one byte. But, by default, it truncates the output file, so that the end of file is where dd finished.

$ echo abcdefgh > test1
$ echo 12345678 > test2
$ dd count=1 bs=1 skip=2 seek=2 if=test1 of=test2
1+0 records in
1+0 records out
1 byte copied, 0.000179375 s, 5.6 kB/s
$ cat test2; echo
12c

The GNU manpage I have doesn't seem to explicitly say that, but the POSIX description does:

of=file
Specify the output pathname; [...] If seek=expr is specified, but conv=notrunc is not, the effect of the copy shall be to preserve the blocks in the output file over which dd seeks, but no other portion of the output file shall be preserved. (If the size of the seek plus the size of the input file is less than the previous size of the output file, the output file shall be shortened by the copy. [...])

To prevent that, add the conv=notrunc option:

notrunc
do not truncate the output file

$ echo 12345678 > test2
$ dd conv=notrunc count=1 bs=1 skip=2 seek=2 if=test1 of=test2
1+0 records in
1+0 records out
1 byte copied, 0.00019385 s, 5.2 kB/s
$ cat test2
12c45678

notrunc doesn't make it modify the data that actually is copied, so it's not a "conversion" in that sense, even though it's taken as a flag to conv.

Note that if count= is given, dd does exactly that many read() calls, which means that if you read from a device that can give short reads, the amount of data actually read is not count times bs.

1
  • You can also replace of=file conv=notrunc with 1<> file in Bourne-like shells. Oct 29, 2021 at 13:19
1

Should have looked at full documentation, man dd:

Full documentation at: <https://www.gnu.org/software/coreutils/dd>
       or available locally via: info '(coreutils) dd invocation'

‘of=FILE’ Write to FILE instead of standard output. Unless ‘conv=notrunc’ is given, ‘dd’ truncates FILE to zero bytes (or the size specified with ‘seek=’).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .