The dd Command
Every copying tool covered so far in this course — cp, mv, even LVM’s snapshot concept — operates in terms of files, understood through a filesystem. dd operates one level lower than all of them: it copies raw bytes, block by block, with no awareness of files, filesystems, or partitions at all. That makes it uniquely powerful for cloning entire disks byte-for-byte — and uniquely dangerous, since it will just as happily overwrite an entire disk with equal indifference. This lesson earns every warning box in it.
What dd Actually Does
dd reads from an input and writes to an output, in fixed-size chunks, until the input is exhausted. Its basic syntax looks unlike anything else in this course:
dd if=<input> of=<output> bs=<block-size>if=— input file (or device)of=— output file (or device)bs=— block size, how many bytes to read and write at a time
There’s no source-then-destination positional argument the way cp works — everything is a named key=value pair, and getting if/of backwards silently reverses the entire operation’s direction.
Warning
dd has no confirmation prompt, no “are you sure,” and no dry-run mode. If of= points at a disk with existing data — including, potentially, the disk you’re currently running the operating system from — that data is being overwritten the moment the command starts, with no warning and no way to interrupt cleanly partway through without leaving things in a broken, half-written state. The folk etymology “dd stands for disk destroyer” isn’t official, but it’s not unearned either. Confirm every if= and of= value with lsblk immediately before running any dd command — this is the single most important habit in this entire chapter.
Why Block Size Matters
bs= controls how much data dd reads and writes in a single operation. Too small (the historical default is a mere 512 bytes) and dd spends most of its time on per-operation overhead rather than actually moving data — genuinely, dramatically slower. A larger block size, commonly 4M (4 megabytes), moves far more data per operation and is dramatically faster in practice:
dd if=/dev/sdb of=/dev/sdc bs=4MThere’s no single universally “correct” block size — 4M is a reasonable, commonly used default that balances speed against memory usage, and it’s what every example in this chapter uses.
Seeing Progress
dd is silent by default while it works — consistent with the “no news is good news” convention from the Terminal & Shell Basics chapter, but genuinely unsettling for a command that can run for many minutes with real consequences if something’s wrong. status=progress fixes that:
dd if=/dev/sdb of=/dev/sdc bs=4M status=progressThis prints a running total as the copy proceeds — bytes copied so far, current speed — giving you visibility into a long-running operation instead of staring at a blank terminal wondering if it’s actually working.
Real World Use Cases
Cloning A Disk, Entirely
The clearest use case for dd: copying an entire disk to another disk, byte for byte — partition table, boot sector, every filesystem on it, all in one operation, with no need to separately handle partitioning, formatting, or mounting at all.
sudo dd if=/dev/sdb of=/dev/sdc bs=4M status=progressThis makes /dev/sdc an exact copy of /dev/sdb, down to the byte. Notice this is genuinely different from copying files with cp — dd doesn’t know or care whether a given block contains real data or empty, unused space; it copies everything, which is slower than a file-level copy but produces a truly identical result, including things a file-level copy would never capture, like the partition table itself and the boot code.
Warning
Both disks must be safely unmounted — and ideally, not in active use by anything — before running this. Cloning onto a disk that’s currently mounted, or currently the system’s own root disk, is a reliable way to corrupt a running system.
Creating A Disk Image File
Instead of cloning disk-to-disk directly, dd can just as easily write to a regular file instead of a device — creating a portable image you can store, move, or restore later:
sudo dd if=/dev/sdb of=/home/you/disk-backup.img bs=4M status=progressRestoring is the same operation in reverse — if and of swapped:
sudo dd if=/home/you/disk-backup.img of=/dev/sdb bs=4M status=progressWriting An ISO To A USB Drive
A genuinely common real-world use of dd: writing a bootable ISO image onto a USB drive.
sudo dd if=ubuntu-24.04.iso of=/dev/sdX bs=4M status=progressWarning
of=/dev/sdX here means the whole USB disk, not a partition on it — writing to the wrong /dev/sdX silently destroys whatever was previously on that entire device. This is precisely the scenario where the lsblk-first habit matters most: USB drives frequently get assigned device letters that shift around depending on what else is plugged in, and there is no more common dd disaster than a USB drive letter mistaken for an internal disk, or vice versa.
Wiping A Disk
dd can also be pointed at special input devices instead of a real disk or file — specifically /dev/zero and /dev/urandom, both mentioned back in the Filesystem Hierarchy Standard topic’s discussion of /dev as not-really-files. /dev/zero produces an endless stream of zero bytes on demand; /dev/urandom produces an endless stream of random bytes. Neither one ever runs out, which is exactly why they’re useful as dd inputs for deliberately overwriting a disk:
sudo dd if=/dev/zero of=/dev/sdb bs=4M status=progressThis overwrites the entire disk with zeros — a straightforward way to wipe a disk before disposal or repurposing, though be aware /dev/zero runs until the disk is completely full, which for a large disk can take a genuinely long time. Since there’s no natural end point the way copying a fixed-size file has, you’ll typically just let it run to completion or, for a partial wipe (such as just destroying a partition table at the start of a disk, without touching the entire drive), add count= to limit how many blocks are written:
sudo dd if=/dev/zero of=/dev/sdb bs=4M count=100 status=progressThis writes only 100 blocks (400MB at this block size) rather than the entire disk.
Why You Might Need sync Afterward
Linux buffers writes in memory before actually committing them to disk, for performance reasons — a detail that hasn’t mattered anywhere else in this course, but matters here specifically because dd can report completion before every byte has genuinely reached the physical disk. This is particularly relevant for removable media like USB drives, where unplugging immediately after dd finishes can leave the write incomplete.
syncRunning sync explicitly forces any buffered writes to actually flush to disk before you consider the operation truly finished — worth running as a deliberate final step any time dd’s target is removable media you’re about to physically disconnect.
Important
sync actually force flushes anything your memory is holding right now, not necessarily be only the buffer of dd program — other programs too, and hence you can use conv=sync will is dd specific as such:
sudo dd if=/dev/zero of=/dev/sdb bs=4M count=100 status=progress conv=syncFor more information, see this askubuntu answer. Also dd man page and sync man page.
A Quick Comparison With cp
| Scope | cp | dd |
|---|---|---|
| Operates on | Files, through the filesystem | Raw bytes, bypassing the filesystem entirely |
| Copies unused space | No — only actual file content | Yes — every block, used or not |
| Preserves partition table / boot sector | No | Yes |
| Speed for a mostly-empty disk | Faster (skips empty space) | Slower (copies everything regardless) |
| Right tool for | Copying specific files or directories | Cloning an entire disk or creating a disk image |
What’s Next
You now have the full storage toolkit — partitioning, filesystems, LVM, measuring usage, and low-level cloning. The last chapter in this section pulls several of these together into a single, realistic, end-to-end scenario: attaching a brand new second disk to a system and getting it fully into service.