Datenrettung von defekten Festplatten, SD-Karten, Micro-SD und SSDs unter Linux
Eine defekte Festplatte, eine SD-Karte die plötzlich nicht mehr erkannt wird oder ein USB-Stick mit wichtigen Fotos drauf – solche Situationen kennt wohl jeder. Bevor man in Panik verfällt oder teure Datenrettungsdienste beauftragt: Mit Linux und ein paar kostenlosen Tools lässt sich erstaunlich viel selbst retten. In diesem Beitrag zeige ich dir den kompletten Weg von der ersten Diagnose bis zur sortierten Wiederherstellung.
Wichtig: Ruhe bewahren und nichts überschreiben
Der größte Fehler bei der Datenrettung ist Hektik. Jeder Schreibvorgang auf dem defekten Datenträger kann Daten unwiderruflich zerstören. Deshalb gilt:
- Nicht versuchen, den Datenträger zu reparieren (kein
fsck, keinchkdsk). - Nicht neue Daten draufschreiben.
- Nicht das Betriebssystem davon starten lassen.
Der erste und wichtigste Schritt ist immer: ein bitgenaues Abbild (Image) des Datenträgers erstellen. Damit arbeiten wir dann in Ruhe weiter, und der defekte Datenträger kann danach in die Schublade wandern.
Voraussetzungen
Für die Datenrettung brauchen wir folgende Pakete. Unter Linux Mint, Ubuntu oder Debian installierst du sie mit:
sudo apt update
sudo apt install gddrescue testdisk imagemagick
Das Paket gddrescue enthält das Tool ddrescue, mit dem wir das Disk-Image erstellen. In testdisk steckt auch photorec, das die eigentliche Dateiwiederherstellung übernimmt. imagemagick nutzen wir später, um echte Fotos von Windows-Icons und Thumbnails zu unterscheiden.
Hinweis: Das Paket heißt gddrescue (GNU ddrescue) und nicht ddrescue – das sind zwei verschiedene Programme. Achte darauf, das richtige zu installieren.
Schritt 1: Datenträger identifizieren mit fdisk
Schließe den defekten Datenträger an (USB-Adapter, Kartenleser, etc.) und finde heraus, welches Device er bekommen hat:
sudo fdisk -l
Die Ausgabe zeigt alle angeschlossenen Datenträger mit ihren Partitionen. Das sieht dann ungefähr so aus:
Disk /dev/sda: 238,47 GiB, 256060514304 bytes, 500118192 sectors
...
Disk /dev/sdb: 298,09 GiB, 320072933376 bytes, 625142448 sectors
Disk model: My Passport 0740
Units: sectors of 1 * 512 = 512 bytes
Device Boot Start End Sectors Size Id Type
/dev/sdb1 * 2048 1026047 1024000 500M 7 HPFS/NTFS/exFAT
/dev/sdb2 1026048 625141759 624115712 297,6G 7 HPFS/NTFS/exFAT
In diesem Beispiel ist /dev/sda die interne SSD und /dev/sdb die externe USB-Festplatte, die wir retten wollen. Merke dir den Devicenamen – im weiteren Verlauf verwende ich /dev/sdb als Beispiel. Pass das an deinen Fall an.
Alternativ kannst du auch lsblk verwenden, das zeigt die Zuordnung etwas übersichtlicher:
lsblk -o NAME,SIZE,FSTYPE,LABEL,MOUNTPOINT
Vorsicht: Verwechsle niemals den defekten Datenträger mit deiner Systemplatte. Ein ddrescue in die falsche Richtung und dein laufendes System ist weg. Lieber dreimal prüfen.
Schritt 2: Disk-Image erstellen mit ddrescue
Jetzt erstellen wir ein bitgenaues Abbild. Dafür brauchst du genug freien Speicherplatz auf einer anderen Platte – mindestens so viel wie der defekte Datenträger groß ist.
sudo ddrescue -d -r3 /dev/sdb /mytmp/hdd-rescue.img /mytmp/hdd-rescue.log
Die Parameter im Einzelnen:
-d– Direct Access, umgeht den Kernel-Cache. Sinnvoll bei defekter Hardware.-r3– Versucht fehlerhafte Sektoren bis zu 3 Mal erneut zu lesen./dev/sdb– Der Quelldatenträger (das ganze Device, nicht einzelne Partitionen)./mytmp/hdd-rescue.img– Zieldatei für das Image./mytmp/hdd-rescue.log– Logdatei, die den Fortschritt speichert.
Die Logdatei ist extrem wichtig: Falls ddrescue unterbrochen wird (Kabel rausgezogen, Rechner abgestürzt), kannst du den Vorgang einfach mit dem identischen Befehl fortsetzen. Das Tool liest dann nur die noch fehlenden Bereiche nach.
Bei einer 320 GB Platte kann das je nach Zustand zwischen einer Stunde und mehreren Tagen dauern. Defekte Sektoren bremsen den Vorgang stark aus. Die Fortschrittsanzeige zeigt dir, wie viele Fehler aufgetreten sind:
GNU ddrescue 1.27
Press Ctrl-C to interrupt
ipos: 156372 MB, non-trimmed: 1536 B, current rate: 33554 kB/s
opos: 156372 MB, non-scraped: 0 B, average rate: 44142 kB/s
non-tried: 163700 MB, bad-sector: 0 B, error rate: 0 B/s
rescued: 156372 MB, bad areas: 0, run time: 59m 2s
pct rescued: 48.85%, read errors: 0, remaining time: 1h 1m
Sonderfall SD-Karten und Micro-SD
Bei SD-Karten ist der Vorgang identisch. Die Karte taucht meist als /dev/mmcblk0 auf (oder bei USB-Kartenlesern als /dev/sdb o.ä.):
sudo ddrescue -d -r3 /dev/mmcblk0 /mytmp/sd-rescue.img /mytmp/sd-rescue.log
SD-Karten haben oft das Problem, dass sie irgendwann komplett den Dienst verweigern. Wenn die Karte schon beim Einstecken nicht mehr erkannt wird (dmesg zeigt Fehler), hilft leider auch ddrescue nicht mehr. In dem Fall bleibt nur ein professioneller Datenrettungsdienst, der den Flash-Chip direkt ausliest.
Schritt 3: Dateien wiederherstellen mit PhotoRec
Jetzt haben wir ein Image und können in Ruhe damit arbeiten. Der defekte Datenträger ist ab jetzt nicht mehr nötig.
PhotoRec durchsucht das Image sektorweise nach bekannten Dateiheadern – es kann also auch Dateien finden, deren Verzeichniseinträge längst überschrieben sind. Das Ergebnis sind Ordner voller Dateien mit kryptischen Namen wie f0012345.jpg. Die Originalnamen sind in der Regel verloren.
Manuell mit PhotoRec
Wer es einmal manuell ausprobieren will:
photorec /d /mytmp/output /cmd /mytmp/hdd-rescue.img wholespace,search
PhotoRec legt im Zielverzeichnis mehrere Unterordner an (recup_dir.1, recup_dir.2, …) und füllt sie mit den gefundenen Dateien. Je nach Imagegröße können das tausende Dateien sein – ein ziemliches Chaos.
Automatisiert mit dem Recovery-Script
Damit man nicht stundenlang manuell sortiert, habe ich ein Bash-Script geschrieben, das den kompletten Ablauf automatisiert: PhotoRec laufen lassen, die gefundenen Dateien nach Typ sortieren und dabei mit ImageMagick echte Fotos von Icons und Thumbnails unterscheiden.
Das Script recover_and_sort.sh wird so aufgerufen:
chmod +x recover_and_sort.sh
./recover_and_sort.sh /mytmp/hdd-rescue.img /mytmp/output
Standardmäßig wird im Modus wholespace gescannt, also die gesamte Partition – das bringt die meisten Ergebnisse. Optional kann man freespace als dritten Parameter übergeben, falls das Dateisystem noch intakt ist und man nur gelöschte Dateien sucht.
Hier das komplette Script:
#!/usr/bin/env bash
set -euo pipefail
# ==========================================================
# recover_and_sort.sh
# Datenrettung aus Disk-Images mit PhotoRec + intelligente Sortierung
#
# Usage:
# ./recover_and_sort.sh <IMAGE> <OUTPUT_DIR> [freespace|wholespace]
#
# Beispiel:
# ./recover_and_sort.sh hdd-rescue.img /mytmp/output freespace
#
# Benötigt: testdisk (photorec), imagemagick (identify), coreutils
# ==========================================================
IMAGE="${1:-}"
OUT_BASE="${2:-}"
SCAN_MODE="${3:-wholespace}"
# --- Argumente prüfen ---
if [[ -z "$IMAGE" || -z "$OUT_BASE" ]]; then
echo "Usage: $0 <IMAGE> <OUTPUT_DIR> [freespace|wholespace]"
exit 1
fi
if [[ ! -f "$IMAGE" ]]; then
echo "ERROR: Image nicht gefunden: $IMAGE"
exit 1
fi
if [[ "$SCAN_MODE" != "freespace" && "$SCAN_MODE" != "wholespace" ]]; then
echo "ERROR: SCAN_MODE muss 'freespace' oder 'wholespace' sein"
exit 1
fi
# --- Abhängigkeiten prüfen ---
need_cmd() {
command -v "$1" >/dev/null 2>&1 || {
echo "ERROR: '$1' fehlt. Installiere z.B. 'sudo apt install $2'"
exit 1
}
}
need_cmd testdisk testdisk
need_cmd photorec testdisk
need_cmd identify imagemagick
need_cmd awk gawk
need_cmd readlink coreutils
mkdir -p "$OUT_BASE"
OUT_BASE="$(readlink -f "$OUT_BASE")"
IMAGE_ABS="$(readlink -f "$IMAGE")"
# ==========================================================
# 1) Partitionen aus Image ermitteln
# ==========================================================
PART_LOG="$OUT_BASE/testdisk_partitions.log"
echo "=== Analysiere Partitionen in: $IMAGE_ABS"
testdisk -l "$IMAGE_ABS" 2>&1 | tee "$PART_LOG" >/dev/null
# Partition-Nummern extrahieren (Zeilen, die mit Zahl beginnen)
mapfile -t PARTS < <(awk '/^[[:space:]]*[0-9]+[[:space:]]/ {print $1}' \
"$PART_LOG" | sort -n | uniq)
if [[ "${#PARTS[@]}" -eq 0 ]]; then
echo "ERROR: Keine Partitionen gefunden. Siehe: $PART_LOG"
exit 1
fi
echo "Gefundene Partitionen: ${PARTS[*]}"
echo "Scan-Modus: $SCAN_MODE"
echo
# ==========================================================
# 2) PhotoRec scripted pro Partition
# ==========================================================
RECOVER_ROOT="$OUT_BASE/recovered_raw"
mkdir -p "$RECOVER_ROOT"
for p in "${PARTS[@]}"; do
PART_DIR="$RECOVER_ROOT/part_$p"
mkdir -p "$PART_DIR"
echo "=== PhotoRec: Partition $p -> $PART_DIR"
photorec /log /d "$PART_DIR" /cmd "$IMAGE_ABS" \
"${SCAN_MODE},${p},search" || true
done
echo
echo "✅ Recovery abgeschlossen. Rohdaten: $RECOVER_ROOT"
echo
# ==========================================================
# 3) Sortieren: nur relevante Dateien, echte Fotos erkennen
# ==========================================================
SORT_DIR="$OUT_BASE/SORTIERT"
mkdir -p "$SORT_DIR"/{Bilder,Dokumente,Tabellen,Praesentationen,PDFs,Texte}
# --- Foto-Filter-Parameter ---
MIN_IMAGE_BYTES=$((300 * 1024)) # 300 KB Mindestgröße
MIN_IMAGE_WIDTH=640 # Mindestbreite in Pixel
MIN_IMAGE_HEIGHT=480 # Mindesthöhe in Pixel
MIN_IMAGE_PIXELS=$((640 * 480)) # ~307.200 Pixel Mindestfläche
# Statistik-Zähler
STAT_TOTAL=0
STAT_FOTOS_OK=0
STAT_FOTOS_SKIP=0
STAT_DOCS=0
copy_to() {
local file="$1" target="$2"
mkdir -p "$SORT_DIR/$target"
cp -n -- "$file" "$SORT_DIR/$target/" 2>/dev/null || true
}
# is_real_photo: Prüft ob ein Bild ein echtes Foto ist
# (nicht Icon/Thumbnail)
# Kriterien:
# 1. Dateigröße >= MIN_IMAGE_BYTES
# 2. Breite >= MIN_IMAGE_WIDTH UND Höhe >= MIN_IMAGE_HEIGHT
# 3. Gesamtpixel >= MIN_IMAGE_PIXELS (fängt 256x256 Icons ab)
# 4. Kein ICO-Format (Windows-Icons werden manchmal als
# .png recovered)
is_real_photo() {
local file="$1"
# Dateigröße prüfen
local size
size="$(stat -c%s "$file" 2>/dev/null || echo 0)"
if [[ "$size" -lt "$MIN_IMAGE_BYTES" ]]; then
return 1
fi
# ImageMagick identify: Format, Breite, Höhe auslesen
local info
if ! info="$(identify -format '%m %w %h' "$file" \
2>/dev/null)"; then
return 1
fi
local fmt width height
read -r fmt width height <<< "$info"
# ICO-Format aussortieren (Windows-Icons)
if [[ "$fmt" == "ICO" || "$fmt" == "CUR" ]]; then
return 1
fi
# BMP unter 100KB sind oft System-Icons
if [[ "$fmt" == "BMP" && "$size" -lt $((100 * 1024)) ]]; then
return 1
fi
# Mindestauflösung prüfen
if [[ "$width" -lt "$MIN_IMAGE_WIDTH" \
|| "$height" -lt "$MIN_IMAGE_HEIGHT" ]]; then
return 1
fi
# Gesamtpixel prüfen (fängt quadratische Icons ab)
local pixels=$(( width * height ))
if [[ "$pixels" -lt "$MIN_IMAGE_PIXELS" ]]; then
return 1
fi
return 0
}
echo "=== Sortiere Dateien aus recovered_raw/ ==="
echo " Foto-Filter: min ${MIN_IMAGE_BYTES} Bytes," \
"min ${MIN_IMAGE_WIDTH}x${MIN_IMAGE_HEIGHT} px"
echo
while IFS= read -r -d '' f; do
STAT_TOTAL=$(( STAT_TOTAL + 1 ))
ext="${f##*.}"; ext="${ext,,}"
case "$ext" in
jpg|jpeg|png|tif|tiff|bmp|heic|nef|cr2|arw|dng|raw|webp)
if is_real_photo "$f"; then
copy_to "$f" "Bilder"
STAT_FOTOS_OK=$(( STAT_FOTOS_OK + 1 ))
else
STAT_FOTOS_SKIP=$(( STAT_FOTOS_SKIP + 1 ))
fi
;;
pdf) copy_to "$f" "PDFs"; STAT_DOCS=$(( STAT_DOCS + 1 )) ;;
doc|docx|odt|rtf) copy_to "$f" "Dokumente"; STAT_DOCS=$(( STAT_DOCS + 1 )) ;;
xls|xlsx|ods|csv) copy_to "$f" "Tabellen"; STAT_DOCS=$(( STAT_DOCS + 1 )) ;;
ppt|pptx|odp) copy_to "$f" "Praesentationen"; STAT_DOCS=$(( STAT_DOCS + 1 )) ;;
txt|md) copy_to "$f" "Texte"; STAT_DOCS=$(( STAT_DOCS + 1 )) ;;
*) ;;
esac
done < <(find "$RECOVER_ROOT" -type f -print0)
echo
# Speicherbedarf berechnen
SIZE_RAW="$(du -sh "$RECOVER_ROOT" 2>/dev/null | cut -f1)"
SIZE_SORTED="$(du -sh "$SORT_DIR" 2>/dev/null | cut -f1)"
SIZE_BILDER="$(du -sh "$SORT_DIR/Bilder" 2>/dev/null | cut -f1 || echo "0")"
SIZE_DOCS="$(du -sh "$SORT_DIR/Dokumente" 2>/dev/null | cut -f1 || echo "0")"
SIZE_PDFS="$(du -sh "$SORT_DIR/PDFs" 2>/dev/null | cut -f1 || echo "0")"
SIZE_TABELLEN="$(du -sh "$SORT_DIR/Tabellen" 2>/dev/null | cut -f1 || echo "0")"
SIZE_PRAES="$(du -sh "$SORT_DIR/Praesentationen" 2>/dev/null | cut -f1 || echo "0")"
SIZE_TEXTE="$(du -sh "$SORT_DIR/Texte" 2>/dev/null | cut -f1 || echo "0")"
echo "============================================"
echo "✅ Sortierung fertig: $SORT_DIR"
echo "--------------------------------------------"
echo " Dateien gesamt gefunden: $STAT_TOTAL"
echo " Echte Fotos übernommen: $STAT_FOTOS_OK"
echo " Icons/Thumbs übersprungen: $STAT_FOTOS_SKIP"
echo " Dokumente/Tabellen/etc.: $STAT_DOCS"
echo "--------------------------------------------"
echo " Speicherbedarf:"
echo " Rohdaten (gesamt): $SIZE_RAW"
echo " Sortiert (gesamt): $SIZE_SORTED"
echo " ├─ Bilder: $SIZE_BILDER"
echo " ├─ Dokumente: $SIZE_DOCS"
echo " ├─ PDFs: $SIZE_PDFS"
echo " ├─ Tabellen: $SIZE_TABELLEN"
echo " ├─ Präsentationen: $SIZE_PRAES"
echo " └─ Texte: $SIZE_TEXTE"
echo "--------------------------------------------"
echo " Rohdaten bleiben unter: $RECOVER_ROOT"
echo "============================================"
Das Script erledigt drei Dinge:
- Partitionen erkennen – Es liest mit
testdiskdie Partitionsstruktur aus dem Image. - PhotoRec pro Partition – Jede Partition wird einzeln gescannt und die Ergebnisse landen in separaten Ordnern.
- Sortierung – Alle gefundenen Dateien werden nach Kategorien in Unterordner einsortiert: Bilder, Dokumente, PDFs, Tabellen, Präsentationen und Textdateien. Bilddateien durchlaufen dabei einen Filter mit ImageMagick: Nur Dateien mit einer Auflösung über 640×480 Pixel und mindestens 300 KB Größe werden als echte Fotos übernommen. Windows-Icons, Thumbnails und Systemgrafiken werden so automatisch aussortiert.
Am Ende gibt das Script eine Zusammenfassung aus:
============================================
✅ Sortierung fertig: /mytmp/output/SORTIERT
--------------------------------------------
Dateien gesamt gefunden: 4832
Echte Fotos übernommen: 1247
Icons/Thumbs übersprungen: 3021
Dokumente/Tabellen/etc.: 564
--------------------------------------------
Speicherbedarf:
Rohdaten (gesamt): 12G
Sortiert (gesamt): 2,4G
├─ Bilder: 1,8G
├─ Dokumente: 312M
├─ PDFs: 187M
├─ Tabellen: 45M
├─ Präsentationen: 82M
└─ Texte: 1,2M
--------------------------------------------
Rohdaten bleiben unter: /mytmp/output/recovered_raw
============================================
Die Rohdaten aus den recup_dir.*-Ordnern bleiben erhalten, falls man später noch einmal manuell nachschauen möchte. Löschen kann man sie, sobald man mit dem Ergebnis zufrieden ist.
Tipps aus der Praxis
Zielplatte vorher prüfen. Nichts ist ärgerlicher als ein abgebrochener Rettungsvorgang, weil die Zielplatte voll ist. Prüfe vorher mit df -h, ob genug Platz da ist. Faustregel: Doppelt so viel wie der Quelldatenträger groß ist (Image + wiederhergestellte Dateien).
Image immer auf eine andere physische Platte schreiben. Nie auf den selben Datenträger, und nach Möglichkeit nicht auf dieselbe physische Platte, auch wenn es eine andere Partition ist.
Bei mechanischen Festplatten auf Geräusche achten. Klackernde oder schleifende Geräusche deuten auf einen Headcrash hin. In dem Fall: Sofort ausschalten und zu einem professionellen Datenrettungsdienst gehen. Jede weitere Minute kann die Platten-Oberfläche weiter beschädigen.
ddrescue in Etappen laufen lassen. Bei stark defekten Platten kann es sinnvoll sein, ddrescue mehrfach mit verschiedenen Parametern laufen zu lassen. Zuerst einen schnellen Durchlauf ohne Retries (-r0), um die lesbaren Bereiche zu sichern. Dann einen zweiten Lauf mit Retries (-r3) für die schwierigen Stellen. Die Logdatei sorgt dafür, dass nichts doppelt gelesen wird.
Gelöschte Dateien: Zeit ist der Feind. Je länger ein Datenträger nach dem Löschen weiter benutzt wird, desto mehr wird überschrieben. Am besten sofort ein Image ziehen und erst danach normal weiterarbeiten.
Fazit
Datenrettung unter Linux ist kein Hexenwerk. Mit ddrescue und photorec hat man zwei mächtige und kostenlose Werkzeuge, die auch bei stark beschädigten Datenträgern noch erstaunlich viel herausholen können. Der wichtigste Grundsatz bleibt: Erst ein Image erstellen, dann in Ruhe wiederherstellen. Und wer seine Daten regelmäßig sichert, muss diesen Artikel hoffentlich nie in der Praxis anwenden.
