A couple of weeks ago I triaged a drawer of old drives and ended up with a recycle pile: six laptop drives that were either failing or worn out. Today was wipe day.

Between them, those six drives had parked their heads nearly 10 million times. Most laptop drives are rated for around 600,000.

The tally

DriveSizeWipe timeAverage speedFun fact
HGST Z7K500500 GB1 h 16 min109 MB/sTicked constantly. Its read-error counter went from 0 to 196,613 in two weeks
Seagate Momentus 7200.4500 GB1 h 39 min84 MB/sMade an occasional “crunch” mid-wipe
Hitachi 7K500320 GB1 h 10 min77 MB/s5.84 million head parks, almost 10× its rating
Seagate Momentus 5400.680 GB23 min59 MB/s2,891 failed reads in its lifetime
Toshiba MK8037GSX80 GB36 min37 MB/sHealed 12 unreadable sectors by being overwritten
WD Scorpio Blue250 GBn/an/aFailed its own SMART check. Got the drill

That’s 1.48 TB of zeros written in a little over five hours, one drive at a time, through one USB adapter.

The safe way to point dd at a disk

Device names like /dev/sdb get reused every time you swap a drive, which is exactly how people wipe the wrong one. So the wipe went into a small script that refuses to run unless the drive’s serial number matches the one I pass in:

#!/bin/bash
# Usage: bash wipe-disk.sh <drive-serial>
set -u
SERIAL=${1:?usage: bash wipe-disk.sh <drive-serial>}
DEV=/dev/disk/by-id/usb-<adapter-id>    # the USB adapter's stable name

if ! sudo smartctl -i "$DEV" | grep -q "Serial Number: *$SERIAL\$"; then
    echo "The drive in the adapter is not $SERIAL. Nothing was written." >&2
    exit 1
fi
if findmnt -rn -o SOURCE | grep -q "^$(readlink -f "$DEV")"; then
    echo "A partition on this drive is mounted. Unmount it first." >&2
    exit 1
fi

sudo dd if=/dev/zero of="$DEV" bs=4M oflag=direct status=progress
sync

One pass of zeros is plenty for a spinning drive. The “No space left on device” at the end just means dd reached the last sector.

I did all this with Claude Code alongside me. It happily read SMART data, ran self-tests and checked the results, but its auto mode flatly refused to run the dd itself (“Irreversible Local Destruction”). Honestly, that’s the right call. It wrote the script and I pulled the trigger.

My first attempt at pasting the one-liner version wrapped across three lines in the terminal. The first line ran grep with no pattern, the second line tried to run the serial number as a command (TF05…: command not found), and the third was a pile of dd options with no dd in front of them. Nothing was written. The guard did its job by accident. After that, everything went through the script.

Then check that it’s actually zero

A wipe that “finished” isn’t the same as a wipe that worked. After each one I sampled the disk at intervals, always including the last 16 MB, and counted non-zero bytes:

import os
dev, size, chunk = "/dev/sdX", 500107862016, 16 << 20
fd = os.open(dev, os.O_RDONLY)
for gb in (0, 100, 200, 300, 400, 499):
    off = min(int(gb * 1e9), size - chunk) // 4096 * 4096
    os.lseek(fd, off, 0)
    b = os.read(fd, chunk)
    print(gb, "GB:", len(b) - b.count(0), "non-zero bytes")

That check caught something. The HGST had been “wiped” two weeks earlier, except I’d unplugged it at about the two-thirds mark. The start of the disk was zeros, but a 64 MB sample at 499 GB came back 65 million bytes non-zero. The old data was still sitting there at the end of the disk. Today’s full pass fixed that, and every sample on every drive came back zero.

What dying drives sound like

The HGST ticked constantly. That was the head-load mechanism: every few seconds it parked the heads off the platters and loaded them back on. It’s done that almost two million times.

The Seagate 500 GB crunched every so often, during a wipe that should have been a smooth, steady hum. A straight start-to-finish write shouldn’t make the heads jump around. An occasional crunch means they’re re-seeking or recalibrating, and its “command timeout” counter ticked up by one while I watched. With 46 bad sectors already replaced, it’s on its way out.

The WD Scorpio didn’t get the chance. It fails its own health check (541 replaced sectors, past its failure threshold, and 53,888 logged errors), and a wipe on a drive like that can crawl for hours. A drill takes two minutes, and nobody is reading those platters again. Wear eye protection; some platters are glass.

The HGST’s last surprise

Before wiping the HGST, I read some samples off it to see what was left, and the read speed was all over the place:

PositionRead speed
0–100 GB125–133 MB/s
200–300 GB60–65 MB/s
330–360 GB10–27 MB/s
499 GB1.6 MB/s

A healthy drive slows down smoothly toward the inner tracks. It doesn’t drop to 1.6 MB/s. It wasn’t logging errors either, so it was quietly retrying reads until they worked. Its read-error counter, which on Hitachi/HGST drives normally sits at 0 for life, had gone from 0 to 196,613 since I last checked. Writing was fine, at a steady 109 MB/s across the whole disk. Reading was where the worn heads showed.

Bonus round: USB extension cables lie

I also tested a Samsung 860 EVO SSD in a UGREEN enclosure, plugged in through a USB extension cable:

ConnectionUSB linkRead speed
First extension cable480 Mb/s (USB 2.0)40 MB/s
Second extension cable5 Gb/s (USB 3)420 MB/s
KVM switch behind the laptop dock5 Gb/s (USB 3)441 MB/s

Same SSD, same enclosure. The first cable just doesn’t carry the extra wires USB 3 needs, so everything quietly fell back to USB 2.0. Nothing warns you about this. Check lsusb -t and look at the speed at the end of the line.

Gotchas, collected

  • Guard dd with the serial number, not /dev/sdX. Device names move every time you swap a drive.
  • Check that a wipe worked, especially near the end of the disk. An interrupted wipe leaves data exactly where you’re least likely to look.
  • Paste long commands into a script instead of the terminal. Line wrapping can turn one command into three different ones.
  • Turn off desktop automount while doing this. My file manager mounted the failing Scorpio read-write the moment it was plugged in.
  • Overwriting “pending” sectors can fix them. The Toshiba’s 12 unreadable sectors went to 0 with no spares used: the data in them had faded, but the surface was fine.
  • Bus-powered enclosures and 7200 rpm laptop drives don’t always mix. Wipes went through a self-powered dock, plugged straight into the laptop.
  • Not every dead drive needs a wipe. If the drive fails its own health check, a drill is faster and more certain.

Six drives out, roughly 10 million head parks retired, and the keep pile is now just the drives that deserve to be kept.