I am using a Win7 machine and a bunch of Pis. Some of them took weeks to configure. I would like to backup their SD cards in case they break. It should be backed up so that if it breaks I could simply buy a new card and reload the backup onto it and plug into the Pi. When I put the cards in my SD card reader on the Windows machine, it does not recognize it as containing files.


4 Answers 4


A disk imager should be able to make a full image of your card, even if the underlying OS can't read the partitions on that card. Win32DiskImager is popular on Windows. The image will be the size of the full card, whether or not you actually use all of the space, so a 32 GB card will yield a 32 GB image file. You do have to ensure that the target disk is larger than the source image.


Yes it can be done. There is an easy and a complicated solution. I'm only able to describe it on a unix system e.g. a mac or linux. But you can use any VM to emulate e.g. linux on windows.


sudo dd bs=1m if=path_of_your_image.img of=/dev/<disknumber>
e.g. disknumber = disk4
    ctr + T
        shows status

if is the input => the path to your raspberry sd card of is the output file e.g. myBackup.img

If you want to roll back the backup you can then change if and of. The image size is the size of the SD card.


but better (because it shrinks the image to the space which is really used). This only works on a linux machine. I run ubuntu with parallels.

Copy this script to any_filename.sh and execute it:



# sanity checks on the command line parameters
if [ "${device}" == "" ]; then
    echo "Please specify device, e.g. $0 /dev/sda <filename>" 1>&2;
    exit 1;

if [ "${outfile}" == "" ]; then
    echo "Please specify filename, e.g. $0 <device> zymbit.img.zip" 2>&1;
    exit 1;

# sanity checks on the partition layout
fdisk -l "${device}" | grep -q "${device}1.*W95 FAT32"
if [ "$?" != "0" ]; then
    echo 'The first partition is expected to be FAT32' 1>&1;
    exit 1;

fdisk -l "${device}" | grep -q "${device}2.*Linux"
if [ "$?" != "0" ]; then
    echo 'The second partition is expected to be Linux' 1>&1;
    exit 1;

# converts and pads given bytes into MB
# Takes the given number in bytes and (by nature of integer division) rounds
# the number of bytes down to the nearest hundred bytes.  That value is then
# padded by 200MB.  The padding was determined by trial and error when
# attempting to image a 1.6GB linux partition.
# TODO: determine a better way to calculate the padding.
function convert_bytes()
    local bytes=$1
    local rounded=0

    let rounded="((${bytes}/100000000)+2)*100"

    echo ${rounded}

# start the dangerous stuff
umount "${device}2"

# do not continue of there are errors
set -e

e2fsck -f "${linux_partition}"

# call resize2fs to shrink the partition down to the minimum size it needs to be.
# parse the output to know how big the partition is in bytes
let bytes=$(resize2fs -M "${linux_partition}" 2>&1 | grep -i -e "The filesystem .*is .*blocks long" | sed -e 's/.*is [^ ]* \([0-9]*\) (4k) blocks.*/\1*4096/')
echo "resized partition"

# convert the value in bytes returned by resize2fs to MB
let megs_rounded=$(convert_bytes ${bytes})

# use parted to shrink the partition down.
# when shrinking the partition down parted will prompt for confirmation.  the
# following post notes to append yes to the operation:
# https://bugs.launchpad.net/ubuntu/+source/parted/+bug/1270203/comments/2
parted --align optimal "${device}" unit MB resizepart 2 "${megs_rounded}" yes
echo "resized 2"

# use last value in the `End` column to know how much to image
let total_bytes=$(parted "${device}" unit B print | grep -v '^$' | awk '{print $3}' | tail -n 1 | sed -e 's/B//');
let total_megs_rounded=$(convert_bytes ${total_bytes})

if [ "${optionZip}" == "true" ]; then
    # generate a zip file on the fly
    #time dd bs=1M if=${device} count=${total_megs_rounded} | gzip -9 > ${outfile}
    imgfile=$(echo "${outfile}" | sed -e 's/.zip$//')
    if [ "${imgfile}" == "${outfile}" ]; then

    # drop the .img to disk and then zip so that Macs can read the file
    dd bs=1M if="${device}" of="${imgfile}" count="${total_megs_rounded}"
    echo "copied"

    zip "${outfile}" "${imgfile}"
    echo "zipped"
    rm "${imgfile}"
    dd bs=1M if="${device}" of="${outfile}" count="${total_megs_rounded}"
    echo "copied"

# expand the filesystem back
full_size=$(parted "${device}" print | grep "Disk ${device}" | awk '{print $3}')
parted "${device}" resizepart 2 "${full_size}"
echo "expanded"
# wait up to 10 seconds for the linux partition to show up
for i in {0..9}; do
    [ -e "${linux_partition}" ] && break
    sleep 1

# if the linux partition didn't show up, this will fail
resize2fs "${linux_partition}"
sudo eject "${device}"
echo "done"
exit 0;

I copied this code from zymbit and modified it a bit.

To install the image again I use etcher.io. You have to expand the file system after flashing the image.

Either with raspi-config or by executing this script:

get_init_sys() {
  if command -v systemctl > /dev/null && systemctl | grep -q '\-\.mount'; then
  elif [ -f /etc/init.d/cron ] && [ ! -h /etc/init.d/cron ]; then
    echo "Unrecognised init system"
    return 1

do_expand_rootfs() {
  if [ $SYSTEMD -eq 1 ]; then
    ROOT_PART=$(mount | sed -n 's|^/dev/\(.*\) on / .*|\1|p')
    if ! [ -h /dev/root ]; then
      whiptail --msgbox "/dev/root does not exist or is not a symlink. Don't know how to expand" 20 60 2
      return 0
    ROOT_PART=$(readlink /dev/root)

  if [ "$PART_NUM" = "$ROOT_PART" ]; then
    whiptail --msgbox "$ROOT_PART is not an SD card. Don't know how to expand" 20 60 2
    return 0

  # NOTE: the NOOBS partition layout confuses parted. For now, let's only
  # agree to work with a sufficiently simple partition layout
  if [ "$PART_NUM" -ne 2 ]; then
    whiptail --msgbox "Your partition layout is not currently supported by this tool. You are probably using NOOBS, in which case your root filesystem is already expanded anyway." 20 60 2
    return 0

  LAST_PART_NUM=$(parted /dev/mmcblk0 -ms unit s p | tail -n 1 | cut -f 1 -d:)
  if [ $LAST_PART_NUM -ne $PART_NUM ]; then
    whiptail --msgbox "$ROOT_PART is not the last partition. Don't know how to expand" 20 60 2
    return 0

  # Get the starting offset of the root partition
  PART_START=$(parted /dev/mmcblk0 -ms unit s p | grep "^${PART_NUM}" | cut -f 2 -d: | sed 's/[^0-9]//g')
  [ "$PART_START" ] || return 1
  # Return value will likely be error for fdisk as it fails to reload the
  # partition table because the root fs is mounted
  fdisk /dev/mmcblk0 <<EOF


  # now set up an init.d script
cat <<EOF > /etc/init.d/resize2fs_once &&
# Provides:          resize2fs_once
# Required-Start:
# Required-Stop:
# Default-Start: 3
# Default-Stop:
# Short-Description: Resize the root filesystem to fill partition
# Description:

. /lib/lsb/init-functions

case "\$1" in
    log_daemon_msg "Starting resize2fs_once" &&
    resize2fs /dev/$ROOT_PART &&
    update-rc.d resize2fs_once remove &&
    rm /etc/init.d/resize2fs_once &&
    log_end_msg \$?
    echo "Usage: \$0 start" >&2
    exit 3
  chmod +x /etc/init.d/resize2fs_once &&
  update-rc.d resize2fs_once defaults &&
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "Root partition has been resized.\nThe filesystem will be enlarged upon the next reboot" 20 60 2

  • 1
    I think you want to flip if and of in your easy section (which uses dd). Currently you have it set up to take an img file as and write it to a device node (e.g. a physical device. The OP asked how to take the data off of the SD card an back it up. Hence, we want to create an img file as output, not accept it as input.
    – airfishey
    Sep 13, 2017 at 19:18
  • 1
    Hardly relevant to the OP who is using Windows.
    – Milliways
    Sep 13, 2017 at 23:47

You can save your OS by using SDcard copier application in the raspbian.

For that you just need an extra empty SDcard.

You can do it by.

  1. Format the new sdcard
  2. Insert it Pi using card reader
  3. Open menu->accessories->sd card copier 4.Select the proper device for copy from device(sdcard running in Pi) and copy to device(inserted sdcard)

It takes about 5-10 minutes to complete. After that boot the pi using this new sdcard. And enjoy the same OS which you have it on the old sdcard

  • Can this backup the live running system?
    – Kingsley
    Dec 11, 2023 at 0:31

If you have a big SD card 16 GB, 32 GB etc but you want to save space with backup you can use:

sudo apt-get install gnome-disk-utility

Open disk utility to check witch letter is your usb drive actually has:


In my case a 32GB SD card with Raspberry image on it recognised as: /dev/sde

So I can run:

sudo dd bs=4M status=progress if=/dev/sde | gzip > \
/you-selected-full-path-here/raspberry-images/`date +%Y%m%d`_rpi_image_backup.gz
status=progress gives you progress bar indication
| gzip > compresses the 32 GB total size and not writing the empty space from the 32 GB
`date +%Y%m%d` writes today date in the filename

Output: 20190529_rpi_image_backup.gz

And the size is only 3.5GB. If you want to write this image to a new SD card use:


Also you can write this image made from 32 GB to a 16 GB or 8 GB disk, it is not complaining about that the image is too large anymore.

  • 2
    This doesn't address the question.
    – RalfFriedl
    May 30, 2019 at 9:02
  • I wrote this answer for everybody not just for grather_columbia, who Google "SD card backup". This question is one of the first hits. I can't find this answer anywhere else, that's why I posted here.
    – jturi
    May 31, 2019 at 11:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.