I have a DD image from a 4GB SD card that has two partitions, these two partitions are only using up about 800 MB and as such I wish to reduce the size of the img fie.
Does anyone know of a way to remove the "free space" from the img file?
Super User is a question and answer site for computer enthusiasts and power users. It only takes a minute to sign up.Sign up to join this community
First make sure the free space is actually empty, and doesn't contain leftovers of deleted files. The easiest way to achieve this is to create a huge file on the disk, containing only null bytes, then delete it.
# losetup --find --partscan foo.img # lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT loop0 7:0 0 4096M 0 loop ├─loop0p1 259:0 0 2048M 0 loop └─loop0p2 259:1 0 2048M 0 loop # for part in /dev/loop0p*; do mount $part /mnt dd if=/dev/zero of=/mnt/filler conv=fsync bs=1M rm /mnt/filler umount /mnt done dd: error writing ‘/mnt/filler’: No space left on device dd: error writing ‘/mnt/filler’: No space left on device # losetup --detach /dev/loop0
Then compress it with a tool like
xz. Even at lowest compression levels, a long series of zeros will compress well:
# ls -s 4096M foo.img # gzip foo.img # ls -s 11M foo.img.gz
Note that you must uncompress the image when writing it back to disk. This will uncompress it 'live':
# cat foo.img.gz | gunzip | dd of=/dev/sda
Note that the output device (sda) must be of sufficient size to fit the original image, otherwise data will be lost or corrupted.
An alternative method, if you want to keep using the image – e.g. with a virtual machine – is to convert the raw image to one of the image formats used by virtualization software; e.g. qcow2 for Qemu, VDI for VirtualBox, or VMDK for VMware.
Note that this still requires you to prepare the image by cleaning the free space using the above method.
# qemu-img convert -f raw -O qcow2 foo.img foo.qcow # qemu-img convert -f raw -O vmdk foo.img foo.vmdk
But if it's going to be written to a real disk again, you have to convert it back to a raw image.
resize2fs is much much easier
resize2fs -M xxx.img
you will be asked to e2fsck first - so:
e2fsck -f -y xxx.img
(image must NOT be mounted!)
Note: this will only work if the image is of a single partition, if it's a whole block device with mutiple partitions see above answer...
I also tried it with qemu-img, and it worked like a charm:
qemu-img resize test.img 2G
We are resizing the
test.img to make it 2G (2GB).
Worked flawless for me.
I have used the gparted approach with my Ubuntu 16.10 computer:
1) Map the img file to the next available loop partition with
losetup, as described in previous posts as above
2) Check with
lsblk which loop drive your image file is mapped to, e.g.
sudo gparted /dev/loop0
4) Shrink the loop partition(s) as deemed appropriate; please make sure to have these partitions unmounted.
fdisk /dev/loop0, then enter
p, this will show you the block size and end block number of the various partitions.
dd if=/dev/loop0 of=shrunk_image_file.img, apply to that command the options
count=[EndBlockNumberOfLastLoopPartition+1] and you will have a shrunk and rightsized image file.