dd: Write and Convert Bytes in CI
dd copies data in fixed-size blocks and can slice, pad, or generate exact byte counts.
To build a file of a precise size, extract a byte range, or copy raw bytes with a progress readout, dd is the byte-level workhorse. Its argument syntax is unusual.
What it does
dd reads from if= and writes to of=, in blocks of bs= bytes, for count= blocks, optionally skipping input (skip=) or seeking in output (seek=). It is used in CI to make fixed-size fixtures, carve a byte range out of a file, or write raw bytes with a live progress line.
Common usage
# make a 10 MiB file of zeros
dd if=/dev/zero of=big.bin bs=1M count=10
# random-content fixture with a progress readout
dd if=/dev/urandom of=rand.bin bs=1M count=100 status=progress
# extract 512 bytes starting at offset 1024
dd if=disk.img of=slice.bin bs=1 skip=1024 count=512
# overwrite bytes in place at an offset (do not truncate)
dd if=patch.bin of=target.bin bs=1 seek=100 conv=notruncOptions
| Operand | What it does |
|---|---|
| if=<file> | Input file (default stdin) |
| of=<file> | Output file (default stdout) |
| bs=<n> | Block size (accepts K, M, G suffixes) |
| count=<n> | Copy only n input blocks |
| skip=<n> / seek=<n> | Skip n input blocks / seek n output blocks |
| status=progress | Print transfer progress periodically |
| conv=notrunc | Do not truncate the output file |
In CI
For a random fixture prefer bs=1M count=N over bs=1 count=<bytes>: a large block size is dramatically faster because bs=1 does one read/write syscall per byte. Add status=progress on long copies so the job log shows movement and does not look hung to a watchdog.
Common errors in CI
"dd: unrecognized operand 'status=progress'" means an old or BusyBox dd without that feature (Alpine); drop it or apk add coreutils. "dd: failed to open ...: Permission denied" writing to a device needs privilege. Note dd operands use = and no leading dash: dd -bs 1M is wrong, it is bs=1M. Forgetting conv=notrunc when patching truncates the output at the write point.