18

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?

  • you may want to add what the desired outcome is. ie: image back to the card, to store on CD. – Wayne Jun 22 '13 at 16:41
8

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 gzip or 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.

  • 1
    how can you be sure that all of the files that are currently stored on the partitions aren't physically scattered around on the disk? – Valerio Santinelli Jun 18 '14 at 13:38
  • because I suppose that files aren't written sequentially on the disk and if a file is at the end of the storage, when I cut the size down, I'll lose the content of that file. – Valerio Santinelli Jun 18 '14 at 17:35
  • Because the OP is asking how to shrink a disk image without losing data. If you truncate an image at a certain size you can't be sure the data will be preserved. – Valerio Santinelli Jun 19 '14 at 17:05
  • @ValerioSantinelli: Where exactly do I suggest truncating the image? – grawity Jun 19 '14 at 17:10
  • 1
    @ValerioSantinelli: By using the apropriate filesystem-resize tool for your filesystem, e.g. resize2fs or ntfsresize (Linux has no tool for FAT), before writing it to the smaller device, or by creating a fresh filesystem and copying over just the files. – grawity Jun 20 '14 at 5:39
21

Using 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...

  • Just a note: for multiple partitions, use losetup --find --partscan xxx.img to setup the image file as a loop device. then run lsblk to find the loop device's partitions. – Yihui Xiong Oct 8 '18 at 3:38
  • It looks like it dosen't work for ISO image that contains operating system. After resize system dosen't boot. – S.R Feb 7 at 10:36
  • @S.R Linux operating system? – Rolf Feb 10 at 10:09
  • 1
    This is a very nice answer, but resize2fs are only for extN type partitions. Other types of partitions will require other tools. – Rolf Feb 10 at 10:14
2

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.

  • 1
    Awesome, worked flawless for me too, compressing a Raspbian image. fully working! – ffleandro Mar 19 at 14:48
  • Well, everything is working, however after booting, running df -h shows the original size. How is this possible? – ffleandro Mar 19 at 15:06
  • Apparently, qemu-img doesn't the partition table, so how does it compress the .img? – ffleandro Mar 19 at 15:34
  • I can resize a .img disk to 1M which definitely breaks the disk image. Any idea to make the resize safer? – lesca Apr 29 at 9:01
0

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. /dev/loop0

3) Execute sudo gparted /dev/loop0

4) Shrink the loop partition(s) as deemed appropriate; please make sure to have these partitions unmounted.

5) Execute fdisk /dev/loop0, then enter p, this will show you the block size and end block number of the various partitions.

6) Execute dd if=/dev/loop0 of=shrunk_image_file.img, apply to that command the options bs=[BlockSize] and count=[EndBlockNumberOfLastLoopPartition+1] and you will have a shrunk and rightsized image file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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