This is a little summary of the disk tools I like to use when working with VMware VMs. Most of the time I’m using an OSX host to serve OSX, Linux, and Windows guests so most of these instruction are based on using OSX as the host.

The Platform Used Here

The platform used in this work is:

  1. OSX 10.11.5
  2. GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)
  3. VMware Fusion Version 8.1.1 (3771013)

The PATH environment contains the VMware Fusion.app tools i.e.:

VMWARE="/Applications/VMware Fusion.app/Contents/Library"
PATH="$VMWARE:$PATH"

Bash Function for Shrinking VMDKs

Add the following function to your ~/.bashrc:

# VMWARE
# assumes the PATH is setup
function shrinkVM {

    # path to vmware tool
    VDISKMAN="vmware-vdiskmanager"

    # find all vmx files
    VMX=()
    for name in $(find $1 -iname "*.vmx")
    do
        VMX+=($name)
    done

    # find all vmdk files
    VMDK=()
    for name in ${VMX[@]}
    do
        # get the current vmdk list from the vmx file
        IFS_backup=$IFS
        IFS=$'\n'
        VMDK_sub=($(grep -o "\".*\.vmdk\"" $name))
        IFS=$IFS_backup

        # get the location of these disks
        VMDK_dir=$(dirname $name)

        # append the relative dirs to the listed disks
        #for disk in ${VMDK_sub[@]}
        for ((i=0; i<${#VMDK_sub[@]}; i++));
        do
            disk=${VMDK_sub[$i]}
            disk="${disk%\"}" # remove suffix "
            disk="${disk#\"}" # remove prefix "
            disk=$( echo "$disk" | sed 's/ /\\ /g' ) # deref spaces
            VMDK+=("$(pwd)/${VMDK_dir}/${disk}")
        done
    done

    time {
        for ((i=0; i<${#VMDK[@]}; i++));
        do
            CMD="$VDISKMAN -d ${VMDK[$i]} && $VDISKMAN -k ${VMDK[$i]}"
            echo $CMD
            eval $CMD
        done
    }
}

Update your environment by executing:

$ source .bashrc

Now you can run shrinkVM on your VM directory:

$ shrinkVM ./vmware/Ubuntu64.vmwarevm

Or on your entire collection of VMs:

$ shrinkVM ./vmware/

Linux Guests

According to Time sinker guest OS’s other than windows can’t be auto-cleaned because files that have been removed (i.e. unlinked) still exist on the virtual disk and must be zeroed out before shrinking. Therefore it is necessary to run:

sudo cat /dev/zero > zero; sync; sleep 1; sudo rm zero

If you’re doing this often you may want to alias this:

function zerofs {
    sudo time cat /dev/zero > zero; sync; sleep 1; sudo rm zero
}

NOTE: This is a simple way to zero the file system if you have enough disk space on the host OS to hold the entire VM when the disk is fully expanded with zeros. If not, you can follow these nifty instructions Shrinking VirtualBox Linux images with ZeroFree.

I had to keep a copy of Ubuntu to boot into and use apt-get to install zerofree. I set VMware to boot via CD/DVD, selected Try Ubuntu (this was 20.04). Then ran fdisk -l to list available devices; I chose sda5:

zerofree -v /dev/sda5

Then proceeded to use the shrink script.

Ubuntu Guests

Time sinker also suggests that you clean up any unneeded packages by running (a la Ubuntu Geek):

$ sudo apt-get autoclean; sudo apt-get clean; sudo apt-get autoremove

If you’re doing this often you may want to alias this:

function cleanfs{
    sudo apt-get autoclean; sudo apt-get clean; sudo apt-get autoremove
    zerofs # from the 'Linux Guests' section above
}

Windows 7 Guests

The VMware Tools installed on the guest also seem to have some shrink utils that can be run in the guest itself -nice if you are only running vmplayer on the host (see ServerFault).

$ cd "C:\Program Files\VMWare\VMware Tools"
$ VMwareToolboxCmd.exe disk list # see what disks can be shrunk
$ VMwareToolboxCmd.exe disk shrink c:\\