2026-02-17 21:32:10 +01:00
|
|
|
# Recover files from a corrupted exFAT SD card
|
|
|
|
|
{
|
2026-02-17 21:35:28 +01:00
|
|
|
lib,
|
2026-02-17 21:32:10 +01:00
|
|
|
writers,
|
|
|
|
|
exfatprogs,
|
|
|
|
|
util-linux,
|
|
|
|
|
coreutils,
|
|
|
|
|
findutils,
|
|
|
|
|
gnused,
|
|
|
|
|
}:
|
|
|
|
|
writers.writeDashBin "fix-sd" ''
|
|
|
|
|
set -efu
|
|
|
|
|
|
|
|
|
|
drive="''${1:?Usage: fix-sd /dev/sdX [output-dir]}"
|
2026-02-17 21:35:28 +01:00
|
|
|
output_dir="''${2:-$(${lib.getExe' coreutils "mktemp"} -d "''${TMPDIR:-/tmp}/fix-sd-XXXXXX")}"
|
|
|
|
|
mountpoint="$(${lib.getExe' coreutils "mktemp"} -d "''${TMPDIR:-/tmp}/fix-sd-mount-XXXXXX")"
|
2026-02-17 21:32:10 +01:00
|
|
|
|
|
|
|
|
trap clean EXIT
|
|
|
|
|
clean() {
|
2026-02-17 21:35:28 +01:00
|
|
|
${lib.getExe' util-linux "umount"} "$mountpoint" 2>/dev/null || true
|
|
|
|
|
${lib.getExe' coreutils "rmdir"} "$mountpoint" 2>/dev/null || true
|
2026-02-17 21:32:10 +01:00
|
|
|
}
|
|
|
|
|
|
2026-02-17 21:35:28 +01:00
|
|
|
filenames="$(${lib.getExe' exfatprogs "fsck.exfat"} "$drive" 2>&1 | ${lib.getExe gnused} -nE "s/.* file '(.*?)' is not allocated.*/\1/p")"
|
|
|
|
|
${lib.getExe' coreutils "mkdir"} -p "$mountpoint" "$output_dir"
|
|
|
|
|
${lib.getExe' util-linux "mount"} "$drive" "$mountpoint"
|
2026-02-17 21:32:10 +01:00
|
|
|
|
|
|
|
|
echo "$filenames" | while read -r filename; do
|
|
|
|
|
[ -n "$filename" ] || continue
|
2026-02-17 21:35:28 +01:00
|
|
|
${lib.getExe' findutils "find"} "$mountpoint" -type f -name "$filename" -exec ${lib.getExe' coreutils "cp"} {} "$output_dir" \;
|
2026-02-17 21:32:10 +01:00
|
|
|
done
|
|
|
|
|
|
|
|
|
|
echo "Recovered files saved to $output_dir"
|
2026-02-17 21:35:28 +01:00
|
|
|
${lib.getExe' exfatprogs "fsck.exfat"} "$drive"
|
2026-02-17 21:32:10 +01:00
|
|
|
''
|