Simplifying backups of SD cards
For our media work with Adapting to Scarcity, we use SD cards to store much of the video and audio footage that we get. As part of our normal workflow, we make a disk image copy of the SD card before erasing it to get more footage. I wrote a really basic shell script to facilitate the process - read on to check it out.
Originally, I was just doing a simple 'dd' to clone the card to a disk image - however, this has the drawback of often using up more disk space than necessary. For instance, if you have a 32GB card but there's only 15GB worth of footage on it, doing a dd clone will create an image that takes up 32GB.
So, I started checking how much space the footage actually requires and then creating a new, empty disk image that's roughly the same size as the used space on the original card (I am currently padding the new image with an additional 10MB). Then, copying the full file structure from the original disk to the new disk image.
Here's my script (note that you may [will likely] need to run this as root):
#!/bin/bash
#####################################################################
# Simple disk copy script
#
# This clones a disk to a disk image, with the new disk image resized
# to roughly match the amount of information actually on the old
# disk. If you do just a basic dd clone on a disk, the new image
# will require the same amount of space that exists on the old disk -
# if you're doing many backup images, this can quickly devour and
# waste a lot of space.
#
# Usage example:
# ./disk_copy.sh /mount/original_disk /path/to/new/image.img
#
# Note that the original disk must be mounted.
#
# Author: Arthur Richards (awjrichards [at] gmail [dot] com)
# Copyright: None, just please don't use for evil.
# Date: 12 March 2010
#####################################################################
#usage guide
USAGE="usage: $0 [mounted disk to copy] [output file]"
if [ -z "$1" ]; then
echo "$USAGE"
exit 1
fi
if [ -z "$2" ]; then
echo "$USAGE"
exit 1
fi
#calculate size of new disk image - pad it with 10MB
#DISK_SIZE=$((`df | grep "$1" | awk '{print $3}'`+10240))
DISK_SIZE_RAW=$(df | grep $1 | awk '{print $3}')
DISK_SIZE_ADJUSTED=$(( $DISK_SIZE_RAW + 10240 ))
echo "Input: $1"
echo "Output: $2"
echo "Output disk size: $DISK_SIZE_ADJUSTED"
#make an empty disk image
dd if=/dev/zero of="$2" bs=1k count="$DISK_SIZE_ADJUSTED"
#format empty disk image
mkfs -t vfat -F 32 "$2"
#prepare temp dir where we'll mount the disk image
TMPDIR=$(mktemp -d)
rm -rf $TMPDIR
mkdir $TMPDIR
#mount new disk image
mount -o loop -t vfat $2 $TMPDIR
#copy complete dir strcuture/files from disk to new disk image
cp -rf "$1"/* $TMPDIR
#umount new disk image and clean up
umount -d $TMPDIR
rmdir $TMPDIR
echo "Disk copy complete"If you have any thoughts or suggestions, I'd love to hear them - I'm fairly inexperienced in the world of shell scripting and am sure I left some stones unturned.
Update: Got some good advice by my buddy Rob about the script, using some safer techniques. The script is now updated following his suggestions.
Update: My other buddy Rob(ert) suggested I mention the key point that this script will likely need to be run as root. So I did.
Thanks Robs!




Post new comment