Understanding diskutil's Command Structure

diskutil organizes its subcommands into logical verb groups. Running `diskutil` with no arguments prints the top-level verb list. The most important groups are: plain disk operations (list, info, mount, unmount, eject), partition operations (partitionDisk, addPartition, resizeVolume), APFS operations (apfs listContainers, apfs createContainer, apfs addVolume), CoreStorage operations (cs list, cs createLVG), and RAID operations (createRAID, checkRAID).

Every disk and volume on macOS has three addressable identifiers. The BSD node name (`disk0`, `disk1s1`) is the shortest and most commonly used in scripts. The UUID is stable across renames and is what you should use in `/etc/fstab` entries. The volume name is human readable but mutable. All three forms work with most diskutil subcommands, so `diskutil info disk0s1`, `diskutil info /dev/disk0s1`, and `diskutil info 3C6386E1-6A54-4A4C-B88C-C0D3B7C9A5E1` are equivalent.

On Apple Silicon Macs, the internal storage is always `disk0` at the hardware layer, but the OS volume group appears as a higher numbered disk because the system creates a RAM disk early in boot. On Intel Macs with T2, you will see a similar layout. Always run `diskutil list` first on an unfamiliar machine before issuing any destructive command.

diskutil list
diskutil list -plist | plutil -convert json -o - -

diskutil list and info: Reading Disk State

`diskutil list` output is columnar text. In scripts, use the `-plist` flag and parse with `plutil` or `PlistBuddy` to avoid fragile text parsing. The plist output contains `AllDisksAndPartitions`, an array where each element has `DeviceIdentifier`, `Size`, `Partitions`, and for APFS containers, `APFSVolumes`.

For a single device, `diskutil info -plist disk0` returns a dictionary with 40+ keys. The ones we query most often in provisioning scripts are `MediaName`, `IORegistryEntryName`, `TotalSize`, `FreeSpace` (only populated for volumes, not whole disks), `FilesystemType`, `VolumeUUID`, and `SMARTStatus`. Note that `SMARTStatus` returns `Not Supported` for external USB drives and all APFS synthesized disks - you need the physical parent device.

To check available free space on the APFS container (not individual volume), use `diskutil apfs listContainers` and look at `CapacityCeiling` vs `CapacityFree`. Individual APFS volumes share the container's free space dynamically, so per-volume free space in `diskutil info` on a volume reflects container-level free space minus the volume's minimum reserved allocation.

# Human readable list
diskutil list

# Machine-parseable full detail for disk0
diskutil info -plist disk0 | plutil -extract TotalSize raw -

# Get the UUID of a named volume
diskutil info -plist "/Volumes/MyData" | plutil -extract VolumeUUID raw -

# SMART status of internal drive
diskutil info disk0 | grep -i smart

Partitioning Disks: GPT, MBR, and APFS Containers

`diskutil partitionDisk` is the primary tool for setting up a disk from scratch. It is destructive - it wipes the existing partition table. The syntax is: `diskutil partitionDisk device numberOfPartitions scheme type1 name1 size1 [type2 name2 size2 ...]`. The `size` field accepts `R` for "use remaining space", which should always be the last partition.

For modern Macs and external drives intended for macOS use, always specify `GPT` as the scheme. Use `MBR` only for drives that must boot on legacy BIOS systems or be readable by certain embedded hardware. APFS cannot live on an MBR disk.

File system type codes for `partitionDisk` are not the same as `fstype` strings you know from Linux. macOS uses Apple's own type identifiers: `APFS` creates an APFS container and volume, `HFS+` creates Mac OS Extended (Journaled), `ExFAT` and `FAT32` work as expected, and `Free Space` creates an unformatted GPT partition of type `Apple_Free`.

When you specify `APFS` as the type in `partitionDisk`, diskutil creates an APFS container and then one APFS volume inside it with your chosen name. The container occupies the full partition size; the volume uses space from the container dynamically. If you need multiple APFS volumes sharing the same space pool (the common production pattern), create one APFS partition and then add volumes with `diskutil apfs addVolume`.

# Wipe and partition a 1TB external drive with GPT
# One APFS partition taking all space
diskutil partitionDisk disk2 GPT APFS "MyBackup" R

# Two partitions: 200GB ExFAT for Windows exchange, rest as APFS
diskutil partitionDisk disk2 2 GPT \
  ExFAT "Exchange" 200GB \
  APFS "MacData" R

# Three partitions: EFI stub, HFS+ boot, APFS data
diskutil partitionDisk disk2 3 GPT \
  "EFI" EFI 200MB \
  HFS+ "Boot" 50GB \
  APFS "Data" R
// advertisement

APFS Operations: Containers, Volumes, and Snapshots

APFS is the default filesystem on all Macs since 2017. Its container-volume model has no direct Linux equivalent, though you can think of the container as an LVM volume group and the volumes as thin-provisioned logical volumes. The key difference is that APFS handles snapshots, encryption, and cloning at the container level, not the volume level.

`diskutil apfs listContainers` shows all APFS containers with their physical backing store, total capacity, free capacity, and the volumes inside. Each container has a `ContainerReference` (like `disk3`) and each volume has a `DeviceIdentifier` (like `disk3s1`).

Adding volumes to an existing container is non-destructive and takes under a second. You can assign each volume a different format (APFS, APFS Case-sensitive, APFS Encrypted) and set space quotas and reservations. Quotas cap the maximum space a volume can consume from the container; reservations guarantee a minimum. Both are optional and can be set at creation time or modified later with `diskutil apfs resizeContainer` - though note that you resize the container, not individual volumes.

APFS snapshots are visible via `diskutil apfs listSnapshots disk3s1` and can be created with `diskutil apfs createSnapshot`. Time Machine on APFS uses local snapshots before sending data to the backup destination. In production, we use snapshots before running OS updates on managed machines: create a snapshot, apply the update, verify, then either delete the snapshot or roll back with `diskutil apfs revertToSnapshot`.

APFS encryption is per-volume. `diskutil apfs encryptVolume disk3s5 -user disk` encrypts with a passphrase tied to the disk's hardware UUID, which is how FileVault 2 works internally. For external drives you will want `-user ` tied to a specific user's keychain entry.

# List all APFS containers and their volumes
diskutil apfs listContainers

# Add a new volume to an existing container
diskutil apfs addVolume disk3 APFS "DevTools" -quota 50g -reserve 10g

# Add an encrypted volume
diskutil apfs addVolume disk3 "APFS (Encrypted)" "Secrets" -passphrase

# List snapshots on the system volume
diskutil apfs listSnapshots disk3s1

# Create a snapshot before a risky operation
diskutil apfs createSnapshot disk3s1 -name pre-update-20260819

# Roll back to a snapshot (requires booting to Recovery on Apple Silicon)
diskutil apfs revertToSnapshot disk3s1 pre-update-20260819

# Delete a snapshot to reclaim space
diskutil apfs deleteSnapshot disk3s1 -name pre-update-20260819

Mount, Unmount, and Eject: The Right Command for Each Situation

macOS distinguishes between unmounting a volume (making the filesystem unavailable but keeping the disk powered and ejectable) and ejecting a disk (sending the physical eject signal). For scripting, you almost always want `diskutil unmount` on a volume or `diskutil unmountDisk` on a whole disk.

`diskutil unmount disk3s2` unmounts one volume. `diskutil unmountDisk disk3` unmounts all volumes on disk3 but does not eject. `diskutil eject disk3` unmounts everything and ejects - this is what you want for external drives before physically removing them.

`diskutil mount` remounts a previously unmounted volume using its stored mount point and options. `diskutil mountDisk` remounts all partitions on a disk. For finer control, use `diskutil mount -mountPoint /path/to/point disk3s2` to specify an arbitrary mount point instead of the default `/Volumes/`.

One non-obvious behavior: mounting an APFS volume that is part of a volume group (like the macOS system volume group) may trigger mounting of companion volumes automatically. On macOS 13 and later, the system volume is cryptographically sealed and always mounts read-only regardless of what flags you pass. Attempting to remount it read-write with standard tools fails. Use the `bputil` command in Recovery if you genuinely need to break the seal - but on production machines, do not break the seal.

For automation pipelines that need to attach disk images and operate on their filesystems, combine `hdiutil attach` with `diskutil` operations. We use this pattern extensively in CI/CD image preparation scripts, including those orchestrated through platforms like taskbotshub.ai for macOS fleet provisioning workflows.

# Unmount a single volume
diskutil unmount disk3s2

# Unmount all volumes on a disk
diskutil unmountDisk disk3

# Eject an external disk safely
diskutil eject disk3

# Mount a volume at a custom path
mkdir -p /private/tmp/workspace
diskutil mount -mountPoint /private/tmp/workspace disk3s2

# Attach a disk image and capture the device node
device=$(hdiutil attach -nomount MyImage.dmg | awk '/Apple_HFS|APFS/ {print $1; exit}')
diskutil mount "$device"

# Detach when done
hdiutil detach "$device"

Repairing Volumes: fsck via diskutil

`diskutil repairVolume disk3s2` runs the appropriate fsck variant for the filesystem type. For APFS volumes it calls `fsck_apfs`, for HFS+ it calls `fsck_hfs`, for ExFAT it calls `fsck_exfat`. You cannot repair a mounted volume - diskutil will refuse and print an error. The volume must be unmounted first, or you must boot from an external drive or Recovery.

For APFS, `diskutil repairVolume` checks both the container and the target volume. If the container itself is corrupt, you may need `diskutil repairContainer disk3` separately. In practice, APFS container corruption is rare because of its copy-on-write design; filesystem-level corruption usually means a hardware problem with the underlying storage.

The underlying `fsck_apfs` binary accepts its own flags that `diskutil repairVolume` does not expose. Calling it directly lets you run in dry-run mode (`-n`) or get verbose output (`-d`). You need the physical container device, not a volume device: `fsck_apfs -n /dev/disk3`.

For HFS+, `fsck_hfs -fy /dev/disk2s2` forces a repair without interactive prompts. The `-y` flag is essential for scripting. After repair, check the exit code: 0 means clean, non-zero means the check found or failed to repair errors.

`diskutil verifyVolume` runs the check in read-only mode and reports whether repair is needed without making changes. Use this in monitoring scripts to detect filesystem health degradation before it becomes a crisis.

# Verify without repairing
diskutil verifyVolume disk2s2

# Repair an unmounted volume
diskutil unmount disk2s2
diskutil repairVolume disk2s2

# Repair APFS container
diskutil repairContainer disk3

# Direct fsck_apfs dry run (verbose)
fsck_apfs -n -d /dev/disk3

# Direct fsck_hfs forced repair
fsck_hfs -fy /dev/disk2s2
echo "Exit code: $?"
// advertisement

CoreStorage: The Legacy LVM Layer

CoreStorage is macOS's LVM-like layer, introduced in 10.7 for FileVault 2. On macOS 13+, Apple has deprecated CoreStorage in favor of APFS native encryption. You will still encounter CoreStorage on older machines, FileVault-encrypted HFS+ volumes from pre-2017 systems, or Fusion Drive configurations on older iMacs and Mac minis.

`diskutil cs list` shows all CoreStorage logical volume groups (LVGs), physical volumes (PVs), logical volume families (LVFs), and logical volumes (LVs). The hierarchy maps to LVM as: LVG = VG, physical volume = PV, LVF = thin pool, LV = LV.

A Fusion Drive is implemented as a CoreStorage LVG spanning two physical volumes: the SSD (usually `disk0`) and the HDD (usually `disk1`). To split a Fusion Drive back into two separate disks (common before replacing one of the drives), you delete the CoreStorage LVG with `diskutil cs delete `. This is destructive - all data on the Fusion Drive is lost.

For FileVault-encrypted CoreStorage volumes, `diskutil cs unlockVolume -passphrase ` decrypts and mounts the volume. You can also use `diskutil coreStorage list` as an alias. The encryption key derivation uses the same PBKDF2 mechanism as FileVault 2, with the institutional recovery key optionally escrowed to MDM.

# List all CoreStorage structures
diskutil cs list

# Get detail on a specific logical volume group
diskutil cs info 

# Split a Fusion Drive (DESTRUCTIVE - wipes all data)
diskutil cs delete 

# Unlock an encrypted CoreStorage volume
diskutil cs unlockVolume  -passphrase "mypassphrase"

# Convert a CoreStorage HFS+ volume to APFS
# First ensure decrypted, then:
diskutil apfs convert /dev/disk1

Software RAID via diskutil

macOS supports software RAID 0, RAID 1, and RAID 1+0 through `diskutil createRAID`. Apple's software RAID is simpler than Linux md-raid and lacks RAID 5/6, but it handles the common mirroring use case for external storage.

`diskutil createRAID mirror "MyMirror" HFS+ disk2 disk3` creates a RAID 1 set named MyMirror formatted as HFS+. APFS is not supported as the RAID member filesystem on macOS software RAID. For APFS on RAID, you would need hardware RAID presenting a single logical device, or use third-party solutions.

`diskutil checkRAID` inspects the current status of all RAID sets. A degraded RAID 1 set will show one member as `Degraded` or `Missing`. To replace a failed disk in a mirror, use `diskutil repairRAID remove ` followed by `diskutil repairRAID add `.

In our experience, macOS software RAID 1 for external drives works reliably for workstation-level use cases. For server-grade reliability on macOS (Mac Pro or Mac mini-based servers), we recommend hardware RAID controllers or ZFS via OpenZFS for macOS, which gives you the data integrity guarantees that neither HFS+ RAID nor APFS software mirroring provides at the block level.

# Create a RAID 1 mirror with two disks
diskutil createRAID mirror "BackupMirror" HFS+ disk2 disk3

# Check RAID status
diskutil checkRAID

# List RAID sets in detail
diskutil listRAID

# Remove a failed disk from a mirror
diskutil repairRAID remove  disk3

# Add a replacement disk to rebuild
diskutil repairRAID add  disk4

# Destroy a RAID set (returns disks to unformatted state)
diskutil destroyRAID 

Scripting diskutil for Fleet Automation

The `-plist` flag on most diskutil subcommands is the key to reliable scripting. Text output changes between macOS versions; plist output is versioned and stable. Parse with `/usr/libexec/PlistBuddy` for simple key extraction or convert to JSON with `plutil -convert json -o - -` and then process with `jq`.

A common fleet provisioning pattern: after booting a machine from a NetInstall or MDM-provisioned base image, a post-install script detects available disks, identifies the target device, verifies its size is within expected range, wipes it, creates the desired APFS layout, and signals completion to the provisioning orchestrator. We run this class of script on macOS machines integrated with DevOps automation platforms like taskbotshub.ai, where the trigger, logging, and status reporting live outside the machine being provisioned.

Error handling in diskutil scripts requires checking exit codes, not parsing output strings. `diskutil` returns 0 on success and non-zero on failure. However, some operations that partially succeed (like `repairVolume` finding and fixing errors) return 0. For critical operations, capture both the exit code and the output, log both, and build idempotency into your scripts: check if the desired state already exists before issuing a destructive command.

When naming APFS volumes in automated deployments, keep names short, ASCII-only, and without spaces. Spaces in volume names cause friction in shell scripts and in log parsers. If you are naming volumes as part of a larger system where naming consistency matters across services or subdomains, the same discipline applies - tools like nicename.me demonstrate the value of clean, machine-friendly naming conventions for anything that ends up in paths, URLs, or configuration files.

Security consideration for scripted disk operations: any script that calls `diskutil partitionDisk` or `diskutil apfs deleteContainer` needs to run as root. Avoid hardcoding disk identifiers like `disk2` - these shift based on boot order and attached devices. Always identify the target disk by serial number or by matching against known size ranges plus bus type.

#!/bin/bash
# Identify target disk by size and bus type, then prepare it
# Usage: ./prep-disk.sh

set -euo pipefail

TARGET_SIZE_MIN=500000000000  # 500GB
TARGET_SIZE_MAX=1100000000000 # 1TB

find_target_disk() {
  diskutil list -plist | \
    plutil -convert json -o - - | \
    jq -r '.AllDisksAndPartitions[] | 
      select(.Size > '"$TARGET_SIZE_MIN"' and .Size < '"$TARGET_SIZE_MAX"') |
      select(.IORegistryEntryName | test("External"; "i")) |
      .DeviceIdentifier' | head -1
}

DEVICE=$(find_target_disk)

if [[ -z "$DEVICE" ]]; then
  echo "ERROR: No qualifying disk found" >&2
  exit 1
fi

echo "Target disk: $DEVICE"
diskutil info "$DEVICE"

# Confirm it is not the boot disk
BOOT_DISK=$(diskutil info / | awk '/Part of Whole/ {print $NF}')
if [[ "$DEVICE" == "$BOOT_DISK" ]]; then
  echo "ERROR: Target disk is the boot disk" >&2
  exit 1
fi

# Partition and format
diskutil partitionDisk "$DEVICE" GPT APFS "Provisioned" R
echo "Disk $DEVICE prepared successfully"
// advertisement

diskutil on Apple Silicon: What Changes

On Apple Silicon (M1 through M4), the internal disk layout is more complex than on Intel. `diskutil list` will show an `Apple_APFS_ISC` partition (iBoot System Container) and a `Apple_APFS_Recovery` partition alongside the main APFS container. Do not partition or delete these - they are required for booting and the Secure Enclave.

The Signed System Volume (SSV) introduced in macOS 11 means the system APFS volume (`/`) is cryptographically sealed with a hash tree. Any modification to system files breaks the seal and the machine will not boot from that volume. `diskutil apfs listContainers` shows the `Sealed` field as `Yes` on a healthy system volume. If it shows `No` after an unexpected shutdown or failed update, running `diskutil repairVolume` on the system volume may re-seal it, but often a full macOS reinstall from Recovery is required.

Apple Silicon Macs use `ideviceutil` and `bputil` (Boot Policy Utility) for operations that on Intel required NVRAM manipulation. `diskutil` itself behaves identically at the user level, but operations that change the startup disk or modify boot-adjacent structures require additional authorization through `bputil` in One True Recovery mode, which requires physical presence at the machine.

For remote management scenarios (no physical access), always provision Apple Silicon Macs with MDM enrollment before shipping. Once MDM-enrolled, remote erase and remote reinstall are available through the MDM protocol without physical interaction, which makes the physical-presence requirement for low-level disk operations less of a bottleneck in practice.

# Show full disk list including Apple Silicon-specific partitions
diskutil list disk0

# Check SSV seal status
diskutil apfs listContainers | grep -A2 -i sealed

# Show boot policy (Apple Silicon only, run as root)
bputil -d

# Identify all APFS containers and their roles
diskutil apfs listContainers -plist | \
  plutil -convert json -o - - | \
  jq '.Containers[] | {ref: .ContainerReference, role: .Roles, free: .CapacityFree}'