Home / Alt manpages / sfdisk(8)

  • sfdisk(8)
  • Admin command
  • linux

Partition a Disk Image Safely with sfdisk

One wrong device path with sfdisk turns a partition table into confetti, so this walks through the whole workflow on a disposable file first. You will create a GPT layout inside a 100 MiB image, dry-run it, apply it, then verify and back it up, all without going near a real disk. Budget about fifteen minutes. You need sfdisk from util-linux and enough free space for a small test image; the installed version here is util-linux 2.42.4.

Safety boundary

Partition-table changes are destructive. The commands below use a regular file under /tmp, not a block device. Do not replace the image path with /dev/sda, /dev/nvme0n1 or another real device until you have a verified backup and a maintenance plan. Creating a filesystem is a separate operation and is deliberately not included.

1. Confirm the installed tool

Check which executable will actually run and what version it is, before you trust anyone's script, including this one:

$ command -v sfdisk
/home/linuxbrew/.linuxbrew/sbin/sfdisk
$ sfdisk --version
sfdisk from util-linux 2.42.4

Your path will likely differ. The local manual documents GPT, DOS, SUN and SGI labels, script input and the options used here, and it notes that sfdisk aligns starts and ends automatically when you use relative sizes or multiplicative suffixes such as MiB. For portable scripts, let sfdisk pick the starts and express sizes in MiB or GiB rather than raw sector offsets.

2. Create a disposable image

Make a 100 MiB regular file. This touches only the temporary file and needs no elevated privileges:

$ IMAGE=/tmp/sfdisk-demo.img
$ truncate -s 100M "$IMAGE"
$ stat --format='size=%s bytes' "$IMAGE"
size=104857600 bytes

Keep IMAGE set in the same shell for every example below. A regular file is fine for learning and review, but it is not a full stand-in for a kernel block device: there are no partition nodes to mount, and any option about kernel rereads has limited meaning here.

3. Dry-run a GPT script

The input below asks for a GPT label, a 32 MiB Linux partition, then a second partition using whatever is left. The blank start fields let sfdisk handle alignment. L is the documented Linux type shortcut; in GPT output it becomes the Linux filesystem type GUID.

$ printf 'label: gpt\n,32M,L\n,\n' \
    | sfdisk --no-act --no-reread "$IMAGE"
Disk /tmp/sfdisk-demo.img: 100 MiB, 104857600 bytes, 204800 sectors
Created a new GPT disklabel
/tmp/sfdisk-demo.imgp1: Created a new partition 1 of type 'Linux filesystem' and of size 32 MiB
/tmp/sfdisk-demo.imgp2: Created a new partition 2 of type 'Linux filesystem' and of size 66 MiB
The partition table is unchanged (--no-act).

The exact disk identifier and some formatting will vary on your machine. What matters is that last unchanged message. --no-act runs the whole operation except the actual write, so this is your chance to catch a wrong size, label or target path before it counts.

4. Apply the reviewed layout

Read the same script again, this time letting it write. --lock=nonblock asks for the recommended device lock but will not wait if another process already holds it. On a real device, use the default blocking lock instead, or stop and investigate a lock failure rather than working around whatever else might be using the disk.

$ printf 'label: gpt\n,32M,L\n,\n' \
    | sfdisk --no-reread --lock=nonblock "$IMAGE"
The partition table has been altered.

This is the first command that actually changes anything. On a real block device it can make existing data inaccessible and may notify the kernel about the new table. The manual recommends locking specifically to avoid races with systemd-udevd and similar tools. --no-reread is handy for a regular image like this one; it is not a general fix for changing a mounted or otherwise busy disk.

5. Inspect and verify the result

List the table, then ask sfdisk to check its own consistency:

$ sfdisk --no-reread --list "$IMAGE"
Disklabel type: gpt
Device                   Start    End Sectors Size Type
/tmp/sfdisk-demo.imgp1    2048  67583   65536  32M Linux filesystem
/tmp/sfdisk-demo.imgp2   67584 202751  135168  66M Linux filesystem
$ sfdisk --no-reread --verify "$IMAGE"
/tmp/sfdisk-demo.img:
No errors detected.

Sector numbers are the authoritative detail here. The first partition starts at sector 2048, which lands on a 1 MiB boundary with 512-byte sectors. Note that the last partition doesn't consume the GPT backup area, so the usable size is a touch smaller than the file itself.

For scripts and monitoring, ask for JSON instead of scraping aligned columns:

$ sfdisk --no-reread --json "$IMAGE" \
    | jq '.partitiontable.partitions | length'
2

The JSON is output only: sfdisk cannot take JSON as input. No jq? Save the output and inspect it as JSON with whatever tool you already trust.

6. Save a restoreable description

A dump is a text script containing the label, sector geometry, types and partition UUIDs. Save one before making a planned change:

$ sfdisk --no-reread --dump "$IMAGE" > /tmp/sfdisk-demo.dump
$ sed -n '1,12p' /tmp/sfdisk-demo.dump
label: gpt
label-id: ...
device: /tmp/sfdisk-demo.img
unit: sectors
first-lba: 2048

To restore that dump, confirm the target path is really the disposable image, then run sfdisk "$IMAGE" < /tmp/sfdisk-demo.dump. A restore reproduces partition types and UUIDs exactly, so do not clone the same dump onto several machines without thinking about duplicate UUIDs: the manual explicitly warns this can cause problems.

For a binary backup of the sectors holding the table, use --backup-pt-sectors, and keep that raw backup separate from the image. Restoring raw sectors needs dd and an exact device offset, so treat it as an expert recovery operation: verify the device more than once and never improvise the offset from memory.

7. Avoid the common traps

  • An omitted start is not sector zero. sfdisk normally chooses the first available aligned sector; the default first start is 1 MiB in.
  • An omitted size means as much space as possible. A bare number without a suffix is a sector count; 32M is a byte value that gets aligned.
  • --label gpt does not by itself create an empty label. Input containing only label: gpt explicitly requests an empty table; otherwise add partition lines.
  • --force disables consistency checking. It is not a routine fix for a warning. Stop, back up and understand the layout first.
  • --wipe and --wipe-partitions can erase signatures. Leave their defaults alone unless you have deliberately planned that data loss.

Made a mistake in the disposable image? Discard it and start again, that is the whole point of using one. On a real disk there is no universal undo: restore a verified dump or binary table backup only after stopping services, unmounting affected filesystems and confirming the exact target.

Done means

  • You checked the installed sfdisk version and target path.
  • You dry-ran the script and reviewed its label, sizes and partition count.
  • You applied it only to a disposable image, then listed and verified the table.
  • You saved a dump before treating the layout as recoverable.
  • You know which omitted values sfdisk chooses for you and which options can erase signatures.