Shrink VDI further by cloning existing Linux file system

The size of VDI can be remarkably large, compare to the actual size of the file system reported by du -h command. Run VBoxManage to compact the VDI can't reduce the disparity either. For example, the file system is 1.2G, but the VDI can be 1.8G. This usually happens when you installed an OS and then deleted a lot of unnecessary software packages, but for unknown reasons, the standard zero fill then compact process wouldn't reclaim the same amount of disk space.

But my experimenting shows that for a fresh new VDI file, I can copy a lot of files to it and then delete them several times, and yet the size of the file system is almost the same as VDI file size in the end. It turns out, that works for the whole file system too.

Another good news is you are offered with an opportunity to choose a smaller dynamically allocated virtual disk. Because while it's easy to enlarge the allocated size of VDI, it's hard for the opposite. Nowadays to install a Linux OS requires at least 10G of hard disk. It takes longer to perform zero filling and compacting with a big virtual disk.

Suppose the file system size is 1.2G, we can create a new virtual disk with size of 2G. Open Settings - Storage of your virtual machine and add the newly created VDI file and start up the VM.

Now we should mount the disk and format it.

ls /dev/sd*
fdisk /dev/sdb
/sbin/mkfs.ext4  /dev/sdb1
mount -t ext4 /dev/sdb1 /mnt/testext4

In this case, the new VDI is identified as /deb/sdb. Run fdisk on the disk and press n to create new partition, you should choose to create primary partition, and then press w to write the configuration. Then we create ext4 file system and mount it.

The following commands copy the whole file system to the new disk and make it bootable.

rsync -aAXv --delete --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/testext4/*","/media/*","/lost+found"} / /mnt/testext4
mount -t proc proc /mnt/testext4/proc
mount -t sysfs sys /mnt/testext4/sys
mount -o bind /dev /mnt/testext4/dev
chroot /mnt/testext4
cp /proc/mounts /etc/mtab
grub-install   /dev/sdb
# if you are using ubuntu or grub2
# update-grub2 /dev/sdb
umount /mnt/testext4/proc
umount /mnt/testext4/sys
umount /mnt/testext4/dev
# change UUID
vi /mnt/testext4/boot/grub/grub.conf
vi /mnt/testext4/etc/fstab
umount /mnt/testext4

Each VDI has its own UUID, you can find out it by running blkid. To boot to correct partition, copy the UUID to fstab and grub.conf of the newly copied file system.

Now you can create a new virtual machine and selected the VDI as hard disk, and boot it.