I have a certain custom Raspbian image downloaded from the internet for a project which I need to use. The file is a little less than 32 GB and I am having issues getting a card which can fit that size. I know that the image definitely does not use all the space and it is probably the OS filling up the space of the SD card it was made on. I tried looking up how to shrink the size of the image but all the methods I saw involved booting the image on a pi which I cannot do since I downloaded the image online. I even got ahold of a 32 GB card to solve the issue but then discovered that the card's true capacity is 31.9 GB, and so my image burning software says I have too little space. Does anyone know how I could shrink the size of this image to 16 GB?
1 Answers
Assuming this is an image of an ext
-formatted partition you can simply use resize2fs
- as available on the pi itself or typical linux installations. So either you have a running linux somewhere, can put the image on an external USB-storage and access it via the pi, or can share it via network (including write premission) and use the pi. If this is given run
fsck name_of_image
resize2fs -M name_of_image
The first command runs a sanity check on the image, the second one resizes it to the minimum possible (i.e. skips empty parts).
Once the image is burnt to the SD, you may want to increase the size of the system to the maximum of the SD. Again resize
will help in that case, however this is only possible when booted from the image or when the SD is directly connected to a pi/linux system. Alternatively windows tools for growing the partition should be available.
EDIT/UPDATE:
As stated in the comments resize2fs
works on images of partitions only. So you would need to create separate images for the partitions.
In the following we'll thus
a) mount the big image you downloaded
b) extract the image of the rootfs partition & resize
Furthermore:
c) prepare a partition table for the new SD
d) copy the old boot and the new, smaller rottfs partitions & extend rootfs to the maximum
a) Mounting a multi-partition disk image
losetup
will do the trick here and create /dev
entries for the disk and partitions on the image:
losetup -Pf big.img
List them with just losetup
(no options). In my example I took one of the official RasPi OS images and got it on loop10
:
losetup
/dev/loop10 0 0 0 0 /data/downloads/2020-12-02-raspios-buster-armhf-lite.img 0 512
Now /dev
will also have the two partitions ready:
ls /dev/loop10*
/dev/loop10 /dev/loop10p1 /dev/loop10p2
Use lsblk
for some more info:
lsblk -o NAME,FSTYPE,LABEL,SIZE /dev/loop10
NAME FSTYPE LABEL SIZE
loop10 1.7G
├─loop10p1 vfat boot 256M
└─loop10p2 ext4 rootfs 1.5G
All as expected. Note that the downloaded file for the light image is ~440MB, yet the image shows 1.7GB. This is due to the partition table.
We'll make a quick trick by writing zeros to empty spaces of the partition image, this will make copying the image faster. Mount the image, create a dummy file, write zeros to it to fill up empty space, remove the dummy file and unmount the device. (Please note that this is only necessary if the image was not created with zeroed empty space). Be aware of dd
-dangers and make sure you have no typos!
mount /dev/loop10p2 /mnt
touch /mnt/dummy
dd if=/dev/zero of=/mnt/dummy
rm /mnt/dummy
umount /mnt
b) Extracting the image of rootfs
dd
is the best tool here, please again be aware of the dangers of dd
and triple check each dd
-command you execute. boot
is no issue, the size should be around 250MB. Yet the big image must be copied once on the hard drive, say under your home:
dd if=/dev/loop10p2 of=/home/joe/local_rootfs.img bs=4M conv=sparce
A bytesize (bs) of 4M should be reasonably fast, conv=sparce will quickly skip empty parts - including the zeros we created in the last step of the previous section.
Now shrink the image to the minimum available:
fsck /home/joe/local_rootfs.img
resize2fs -M /home/joe/local_rootfs.img
It will now be the size of the data only.
c) Preparing the new SD
First of all, we will just copy the master boot record (MBR). Put your SD in and check which device it is with lsblk
. Say it is /dev/sdb
. AGAIN: Make sure you get the right device and be careful with dd
!
We will copy the partition table of the image to the SD:
dd if=/path/to/big.img of=/dev/sdb bs=512 count=1
and delete the second partition in the table, while creating a new one. Example:
cfdisk /dev/sdb
Device Boot Start End Sectors Size Id Type
/dev/sdb1 2048 526335 524288 256M 83 Linux
>> /dev/sdb2 526336 4095999 3569664 1.7G 83 Linux
Navigate to the second partition and delete it, then create a new one with the maximum possible size (default value for new partition), write it and confirm with "yes", then quit. No need to care about which FS-type - this will come from the rootfs partition image.
d) Copy old boot and shrunk rootfs + expand it to SD size
Boot contents may just be copied, thus
dd if=/loop12p1 of=/dev/sdb1 bs=4M
As we copied the partition table, the size will fit exactly. Analogous we copy the content of the now smaller rootfs to the new SD partition:
dd if=/home/joe/local_rootfs.img of=/dev/sdb2 bs=4M
Resize the file system of the rootfs to fill up to the maximum available on the new SD:
resize2fs /dev/sdb2
(Maybe you need to run a fsck
beforehand as above).
Final checks
It might have happened, that the UUIDs of your new partitions have changed. Mount the new rootfs and compare fstab
with the PARTUUIDs of the partitions. Example:
mount /dev/sdb2 /mnt
cat /mnt/etc/fstab
proc /proc proc defaults 0 0
PARTUUID=067e19d7-01 /boot vfat defaults 0 2
PARTUUID=067e19d7-02 / ext4 defaults,noatime 0 1
versus results of blkid
for sdb1
& sdb2
- if need be, update the fstab
file - AND be sure to do it on the mount not your local /etc
!!
Finally run sync
and unmount just to be sure that all got written to the SD card properly before you remove it.

- 109
- 5
-
- The command is
– goldilocks Dec 06 '20 at 16:02resize2fs
. 2. It does not shrink a partition. It shrinks a filesystem in the partition, meaning even if this worked, afterward the image file will still be exactly the same size. 3. It will not work anyway because device images for the Raspberry Pi have two fs partitions in them, andresize2fs
only works on a filesystem image. The same it true WRT yourfsck
invocation. - The command is
-
@goldilocks Ah yes, good point, indeed. Updated with proper way and corrected typo. – FelixJN Dec 08 '20 at 16:22
sudo parted your-32gb.img print
. Ifparted
isn't available then install it. – Ingo Dec 03 '20 at 01:04