Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I've a VirtualBox VM which configured a very large hard disk size (bigger than host). By my mistake, a program on the VM generated lots of log files and the VDI file size keeps growing until there is no space on the host.

Now I've deleted the log files but the VDI file size are not getting smaller after using VBoxManage.exe modifyhd "C:\Virts\mybox-i386.vdi" compact

Is there a way to really compact the VDI file size? Thanks!

share|improve this question
up vote 192 down vote accepted

You have to do the following steps:

  1. Run defrag in the guest (Windows only)
  2. Nullify free space:

    With a Linux Guest run this:

    sudo dd if=/dev/zero of=/bigemptyfile bs=4096k
    sudo rm -rf /bigemptyfile
    

    Or:

    telinit 1
    mount -o remount,ro /dev/sda1
    zerofree -v /dev/sda1
    

    With a Windows Guest, download SDelete from Sysinternals and run this:

    sdelete –z
    
  3. Shutdown the guest VM

  4. Now run VBoxManage's modifyhd command with the --compact option:

    With a Linux Host run this:

    vboxmanage modifyhd /path/to/thedisk.vdi --compact
    

    With a Windows Host run this:

    VBoxManage.exe modifyhd c:\path\to\thedisk.vdi --compact
    

    With a Mac Host run this:

    VBoxManage modifyhd /path/to/thedisk.vdi --compact
    

This reduces the vdi size.

share|improve this answer
7  
For the next person, my command ended up looking like this: "C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" modifyhd "C:\Users\daniel\VirtualBox VMs\....\thedisk.vdi" --compact – Daniel Dec 13 '13 at 17:57
10  
According to the zerofree Linux utility manpage (manpages.ubuntu.com/manpages/natty/man8/zerofree.8.html), zerofree should be better than dd for this job. dd would not been recommended because "it is slow", "it makes the disk image (temporarily) grow to its maximal extent", "it (temporarily) uses all free space on the disk, so other concurrent write actions may fail". Zerofree is available on Ubuntu Linux via apt, or you can compile it yourself. – Dakatine Feb 20 '14 at 13:16
6  
It's fun that the the manpage of zerofree states that with dd other concurrent writes will fail, but zerofree needs the filesystem to be mounted read-only! *duh* – Madarco Feb 25 '14 at 12:04
2  
Tip: Put the two commands on one line like so: dd ...; rm /bigfile, this will minimize the time with a full disk in case you're not waiting for the dd to complete. – jlh May 14 '14 at 17:45
6  
@Dakatine Using VirtualBox 4.3.10, the disk image file did not grow to its maximal extent. VirtualBox is clever enough to not bother writing all zero blocks to the physical disk. – jlh May 14 '14 at 17:50

If running the command in the accepted answer produces an unhelpful error message like this

VBoxManage.exe: error: Cannot register the hard disk 'thedisk.vdi'
{aaaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeeee} because a hard disk 'thedisk.vdi'
with UUID {aaaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeeee} already exists

Simply run the command by the UUID instead of the filename:

VBoxManage.exe modifyhd {aaaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeeee} --compact
share|improve this answer

I'm on a Windows 7 host with Windows guests, Here is a batch file I wrote to Compact all of the VDIs in a folder tree

echo off
mode con:cols=140 lines=200
cls
:: see https://forums.virtualbox.org/viewtopic.php?p=29272#p29272
:: How can I reduce the size of a dynamic VDI on disk?
:: but that page says to use sdelete -s which is suboptimal. 
:: use -z as per http://technet.microsoft.com/en-us/sysinternals/bb897443.aspx

:: First run the sdelete -z c: inside the VMs that zero-out all the free space
:: THEN run this batch file 

Title Compacting Free space on Virtual Machine VMs

:: http://ss64.com/nt/for_r.html
:: http://stackoverflow.com/questions/8836368/windows-batch-file-how-to-loop-through-files-in-a-directory/8836401#8836401

Setlocal EnableDelayedExpansion
:: http://ss64.com/nt/delayedexpansion.html ... 
:: Notice that within the for loop we use !variable! instead of %variable%.

For /R %CD% %%G IN (*.vdi) DO (
 set ohai=%%G
 set lastfive=!ohai:~-5!
:: Skip snapshots which are named {guid}.vdi
 if NOT !lastfive!==}.vdi (
 echo .
 echo Compacting %%G
 "C:\Program Files\Oracle\VirtualBox\VboxManage.exe" modifyhd "%%G" --compact )
 )

pause 
exit

I left the links in the comments so you can (sort of) tell how it works.

edit

Well, after all that, I tried the CloneVDI tool and it did a good job in much less time and in one click.

share|improve this answer
1  
You would think on this sort of site there would be some kind of syntax highlighting for DOS but no. It looks much prettier in Notepad++ – CAD bloke Jan 9 '15 at 10:26
    
@CAD_bloke that would require a parsing engine and when you consider the number of different languages posted on SE you are looking at a HUGE project. Just think how many versions and dialects of DOS there are for example and that's before you even get to Linux etc. – Caltor Sep 17 '15 at 9:58
    
Very good point. Ironically it is highlighted on the stack exchange iOS app. – CAD bloke Sep 17 '15 at 10:32
1  
Yeah CloneVDI is much better and faster way for personal use – VarunAgw Nov 14 '15 at 9:51

I use this for my VDI image mounted to virtual Debian in Windows VirtualBox. It isn't a general solution, but it should at least give you a gist of what I do.

Commands in Debian:

root@debian:~# lsblk  # show partitions
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT 
sdb 8:16 0 128G 0 disk 
└─sdb1 8:17 0 128G 0 part /mnt/web  # THIS IS THE PARTITION OF INTEREST!
sda 8:0 0 64G 0 disk 
├─sda1 8:1 0 61,4G 0 part / 
├─sda2 8:2 0 1K 0 part 
└─sda5 8:5 0 2,7G 0 part 
[SWAP] sr0 11:0 1 56,3M 0 rom
root@debian:~# service mysql stop  # terminate all operations with partition
root@debian:~# service apache2 stop  # terminate all operations with partition
root@debian:~# umount /mnt/web  # unplug partition
root@debian:~# apt-get install zerofree  # install tool for filling in zeros to empty space
root@debian:~# zerofree -v /dev/sdb1  # fill with zeros
root@debian:~# poweroff  # shut down machine

Commands in Windows:

C:\Program Files\Oracle\VirtualBox>VBoxManage.exe modifyhd --compact "D:\VirtualBox VMs\web.vdi"  # convert zeros to empty space

Hope it helps :)

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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