Use dd Safely for Exact Copies, Blocks and Conversions
dd earned the nickname "disk destroyer" one typo in of= at a time. Learn to copy exact bytes, count blocks and convert text with dd without guessing what its operands mean. Allow about fifteen minutes.
The route
Jump straight to the step you need, or tick off Done means at the end.
- You need: a shell and enough space under
/tmpfor a few small test files. - What it touches: the practice commands change only files you create there. The disk-device examples later are warnings and inspection commands, not commands to paste unchanged.
- Tested on: GNU coreutils
dd9.4, from package version9.4-3ubuntu6.3.
1. Check the installed command
Find out which executable your shell runs and note its version:
$ command -v dd
/usr/bin/dd
$ dd --version | head -1
dd (coreutils) 9.4
dd takes operands like if= and of= rather than the usual option style. The core shape is dd if=INPUT of=OUTPUT.
- No
if=: it reads standard input. - No
of=: it writes standard output.
Checkpoint
Never run it until the input and output paths are visibly different and the output is one you intend to create or replace.
2. Copy a file to a new destination
Make a small source file and copy it to a new path. No elevated privileges needed:
$ work_dir=$(mktemp -d /tmp/dd-guide.XXXXXX)
$ printf '%s\n' 'dd copy check' > "$work_dir/source.txt"
$ dd if="$work_dir/source.txt" of="$work_dir/copy.txt" status=none
$ cmp -- "$work_dir/source.txt" "$work_dir/copy.txt"
$ printf 'copy verified: %s\n' "$work_dir/copy.txt"
copy verified: /tmp/dd-guide.XXXXXX/copy.txt
The random part of the directory name changes on every run. cmp prints nothing and returns status 0 when the files match, so the final message only follows a successful comparison.
- Block sizes: input and output both default to 512 bytes. That is a detail of the transfer, not a claim that the file is made of 512-byte records.
status=none: hides the transfer summaryddnormally prints to standard error, while still showing errors. Drop it when you want the statistics.
3. Count blocks, not guesses
count=N stops after N input blocks. A block is the current input block size: 512 bytes by default, or whatever ibs= or bs= says. So count=1 does not always mean one byte:
$ printf '0123456789abcdef' > "$work_dir/sixteen.txt"
$ dd if="$work_dir/sixteen.txt" of="$work_dir/first-eight.txt" bs=1 count=8 status=none
$ wc -c < "$work_dir/first-eight.txt"
8
$ od -An -tc "$work_dir/first-eight.txt"
0 1 2 3 4 5 6 7
Here bs=1 makes each block one byte, so count=8 means eight bytes. Without it, a short regular file would normally be copied in one short input block, and the result would not express the same selection.
Size suffixes are part of dd's syntax, and they bite:
kBmeans 1000.KandKiBmean 1024.MBis decimal;Mis binary.- A trailing
Bon a number counts bytes rather than blocks.
Write the unit explicitly when a boundary matters:
$ dd if="$work_dir/sixteen.txt" of="$work_dir/first-four.txt" bs=1 count=4 status=none
$ wc -c < "$work_dir/first-four.txt"
4
Checkpoint
Verify the byte count with wc -c, or compare a digest, before using the pattern on a large file.
4. Convert data while copying
The conv= operand applies a documented conversion during the transfer. A harmless one, lower case to upper:
$ printf '%s\n' 'mixed Case' > "$work_dir/mixed.txt"
$ dd if="$work_dir/mixed.txt" of="$work_dir/upper.txt" conv=ucase status=none
$ cat "$work_dir/upper.txt"
MIXED CASE
Others include lcase, swab, sync, sparse, and character-set conversions such as ascii and ebcdic. Yes, EBCDIC: dd still speaks mainframe.
Tip
The installed manual accepts a comma-separated list of its own conversion symbols. Do not borrow names from another tool's documentation.
Warning
An existing destination is opened for writing and can be truncated. Write to a new temporary file when the original matters, inspect the result, then replace the old file as a separate deliberate step. If the destination must not already exist, add conv=excl and the command fails instead of overwriting.
5. Use offsets without mixing up units
skip=Nskips input blocks.seek=Nskips output blocks.
Their units follow the input and output block sizes. This pulls four bytes starting at byte offset four:
$ dd if="$work_dir/sixteen.txt" of="$work_dir/offset.txt" bs=1 skip=4 count=4 status=none
$ od -An -tc "$work_dir/offset.txt"
4 5 6 7
Warning
With bs=4096, skip=1 skips 4096 input bytes, not one. If input and output need different units, set ibs= and obs= separately rather than quietly relying on one shared bs=.
Short reads matter when the input is a pipe or device. iflag=fullblock makes dd accumulate input until a full input block is available. It matters for streamed block counts; it will not fix a mistaken offset.
6. Treat devices as destructive targets
Destructive action
Writing to a device can destroy a partition table, filesystem, boot loader or every file on the disk, and a typo in of= is enough. There is no undo for overwritten device data. Elevated privileges may be required, but sudo does not make an unsafe destination safe.
Before any device-writing command:
- Identify the device. Independently, not by its size alone.
- Unmount anything that must not be written.
- Confirm the destination twice.
- Have a recovery plan.
Inspect block devices without writing to them:
$ lsblk -o NAME,PATH,SIZE,TYPE,MOUNTPOINTS
$ findmnt --source /dev/EXAMPLE
Replace /dev/EXAMPLE only with a path you have independently identified.
For imaging:
- Keep the source read-only where your hardware and procedure allow it.
- Write the image to a separate destination.
- Hash or otherwise verify the result.
ddreports that bytes moved; it does not prove the source was the disk you meant or that no storage error happened later.
Tip
Need progress from a running job? Send it USR1 from another terminal using its process ID. The manual documents that it prints I/O statistics and then carries on.
Recovery
Stop a mistaken job promptly, then preserve the output and investigate rather than immediately trying another write.
7. Diagnose failures and clean up
Capture the status straight after dd. Non-zero means the copy or conversion failed, so do not treat a partly written destination as complete:
$ dd if="$work_dir/missing" of="$work_dir/result" status=none
dd: failed to open '/tmp/dd-guide.XXXXXX/missing': No such file or directory
$ printf 'dd status: %s\n' "$?"
dd status: 1
The temporary directory name in the error will vary. Check paths with ls -l and readability with test -r; do not jump to sudo before confirming the path.
When you are done, remove only the temporary directory you created:
$ rm -rf -- "$work_dir"
$ test ! -e "$work_dir" && echo 'temporary test files removed'
temporary test files removed
Warning
This is safe here only because mktemp assigned work_dir. Never swap in an empty variable, a broad directory, or a path copied from an untrusted source.
Done means
- Paths confirmed: you checked the GNU coreutils version and the exact input and output paths.
- Units clear: you can say whether
count,skipandseekare counting bytes or blocks in your command. - Copies verified: you checked a small copy with
cmpand selected sizes withwc -c. - Originals protected: conversions go to a new destination, with
conv=exclfor no-overwrite cases. - Devices respected: you treat device writes as destructive, identify devices independently and know
ddhas no undo. - Clean finish: you captured the exit status and removed only the temporary files you made.