Using the dd command on Linux

Mascote do LinuxPro na oficina, com um HD e um pendrive e blocos de dados fluindo entre eles, ao lado de uma placa de alerta

Note (2026): a 2017 post, revised and expanded. The most useful change: status=progress stopped being a trick and became the normal way to monitor a copy, and today there are better tools than dd for some of the tasks it once handled alone.

The dd copies data block by block, without interpreting what it is copying. That is what allows it to write an ISO to a USB drive, clone an entire disk, or save the boot sector — and it is exactly what makes it dangerous: it obeys without asking, and the wrong device in of= destroys data without confirmation or a trash bin.

This post shows what the command is useful for day to day, with the precautions that separate the tool from disaster.

Where the name comes from

The dd appeared in Unix Version 5 and was created to convert data between ASCII and EBCDIC. The unusual syntax — if=, of=, bs=, instead of the hyphenated flags every Unix command uses — is inherited directly from the DD (Data Definition) statement in IBM's JCL. Some say the resemblance was a programmer's joke. The command is standardized by IEEE Std 1003.1 — now at Issue 8, POSIX.1-2024. But note: the dd from GNU coreutils, which is the Linux version, goes far beyond the standard. POSIX defines if, of, bs, cbs, conv, count, ibs, obs, seek and skip, and only allows the suffixes k, b and x in the block size. status=progress, oflag=, iflag= and the suffix M are GNU extensions — the coreutils manual says so explicitly. The examples in this post apply to Linux; on another Unix, check its manual. The status=progress, in particular, has existed since coreutils 8.24, from 2015.

What makes it powerful on Linux is a characteristic of the system, not the command: here, disks, partitions, memory, and generators like /dev/zero and /dev/urandom are all files. The dd only knows how to read from one file and write to another — everything else follows from that.

Before anything else: identify the correct device

Every disaster with dd starts in the same place: someone thought the USB drive was /dev/sdb and it was /dev/sda. Always check:

lsblk -o NAME,SIZE,TYPE,MOUNTPOINTS,MODEL

You will see something like this — pay attention to the size and model, not just the letter:

NAME   SIZE TYPE MOUNTPOINTS MODEL
sda    931G disk             Samsung SSD 870
├─sda1   1G part /boot/efi
└─sda2 930G part /
sdb     29G disk             SanDisk Cruzer
└─sdb1  29G part /media/nilton/PENDRIVE

The 931 GB one is your system. The 29 GB one is the USB drive. And note: the target of dd is the disk (/dev/sdb), not the partition (/dev/sdb1). Before writing, unmount — but do not eject:

sudo umount /dev/sdb1

Writing an ISO to a USB drive

This is the most common use, and the only command in this post you will probably repeat:

sudo dd if=ubuntu-24.04.2-desktop-amd64.iso of=/dev/sdb bs=4M status=progress oflag=sync

Every part matters:

  • if= — input file, the source. Here, the image.
  • of= — output file, the destination. This is the one that destroys data if it is wrong.
  • bs=4M — block size. The default is 512 bytes, which creates millions of tiny operations and slows writing down. With 4 MB the difference is minutes versus seconds.
  • status=progress — shows bytes copied and speed in real time. Without it, the terminal stays silent and looks frozen.
  • oflag=sync — actually writes instead of accumulating data in cache, so the command only finishes when the data are on the USB drive.

When finished, force the cache to flush before pulling out the device:

sync

One time-saving detail: for a hybrid ISO — which describes practically every current distribution — cp does the same job and is much harder to get wrong:

sudo cp ubuntu-24.04.2-desktop-amd64.iso /dev/sdb && sync

Erasing the MBR

The MBR (Master Boot Record) is the first sector of the disk, with 512 bytes divided as follows:

446 bytes  bootstrap (o código que inicia o boot)
 64 bytes  tabela de particoes
  2 bytes  assinatura 0x55AA
---------
512 bytes

These commands destroy data. Check the device twice.

# apaga o MBR inteiro, INCLUSIVE a tabela de particoes
sudo dd if=/dev/zero of=/dev/sdX bs=512 count=1

# apaga so o bootstrap e PRESERVA a tabela de particoes
sudo dd if=/dev/zero of=/dev/sdX bs=446 count=1

One caveat about those 446 bytes: not all of them are code. The last four (offsets 440 to 443) store the 32-bit disk signature, which Windows records in the BCD and Linux uses to construct the PARTUUID of MBR disks. Zeroing them can prevent Windows from booting and changes the PARTUUID of the partitions. If you want to preserve the signature, the target is bs=440 count=1.

The difference between 512 and 446 is the difference between losing the partitions and merely removing the bootloader. Before either one, save a copy — it is 512 bytes and costs nothing:

sudo dd if=/dev/sdX of=~/mbr-backup.img bs=512 count=1
# para restaurar:
sudo dd if=~/mbr-backup.img of=/dev/sdX bs=512 count=1

A detail that catches people who repeat these commands on a file instead of a device: the dd truncates the output file to the size written. On /dev/sdX this does not happen, because truncating makes no sense on a block device — but dd if=/dev/zero of=imagem.img bs=446 count=1 leaves the image at 446 bytes. When the target is a file, add conv=notrunc.

It is worth knowing that this applies to disks with MBR partitioning. Machines with UEFI and GPT, which are the majority today, store boot files on the EFI partition and have a copy of the GPT table at the end of the disk — there the fix uses gdisk or sgdisk, not dd.

Other worthwhile uses

# criar um arquivo de tamanho fixo (ex.: swap de 2 GB)
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progress
sudo chmod 600 /swapfile && sudo mkswap /swapfile && sudo swapon /swapfile
# para sobreviver ao reboot, acrescente ao /etc/fstab:
#   /swapfile none swap sw 0 0

# medir a velocidade bruta de escrita do disco
dd if=/dev/zero of=teste.img bs=1M count=1024 oflag=direct status=progress

# clonar um disco inteiro para outro do mesmo tamanho ou maior
sudo dd if=/dev/sda of=/dev/sdb bs=64M status=progress conv=noerror,sync

# gerar um arquivo com dados aleatorios
dd if=/dev/urandom of=aleatorio.bin bs=1M count=10

Two details in these examples: the oflag=direct in the speed test bypasses the system cache; otherwise you measure RAM, not the disk. And the conv=noerror,sync in cloning tells dd to keep going when it encounters an unreadable sector, padding with zeros to avoid misaligning the rest — without it, a single bad sector aborts the copy.

When not to use dd

The dd solves many problems, but in 2026 there are better tools for some cases:

  • Disks with bad sectors: use ddrescue (package gddrescue). It makes multiple passes, maps what it managed to read, and lets you resume where it stopped — dd does none of that.
  • Monitoring progress with a bar: pv provides a bar, percentage, and estimated time — pv arquivo.iso | sudo dd of=/dev/sdb bs=4M iflag=fullblock — the iflag=fullblock is not optional here: a pipe buffer on Linux is 64 KB and, without it, bs=4M has no effect at all.
  • Copying regular files: cp and rsync are faster, safer, and know how to handle permissions and links.
  • Creating a large file without writing anything: fallocate -l 2G arquivo is instant because it only allocates space.

And yes: dd appears on LPI exams. It is worth knowing by heart what if, of, bs and count are, and how the MBR's 512 bytes add up.

To keep going