Batch mode and scripting

batch works on several images at once. It takes any number of image files and folders; folders are searched in depth for disk images.

Listing

Without further options, batch only analyses: one line per image with what a trim would free, and a total. This needs no licence.

vdtrim batch D:\VMs
D:\VMs\Debian 13.qcow2: 1.0 GB, a trim would free 246.4 MB
D:\VMs\Fedora Cloud.qcow2: declined: Cluster 0 is compressed; convert the image with qemu-img convert first
D:\VMs\Home Assistant.vdi: 944.1 MB, a trim would free 0 B
D:\VMs\Kali Linux.vhdx: 16.7 GB, a trim would free 971.0 MB
D:\VMs\openSUSE Tumbleweed.vmdk: 747.6 MB, a trim would free 19.0 MB
D:\VMs\Ubuntu Server 24.04.vhd: 30.0 GB, a trim would free 1.3 GB
D:\VMs\Windows 10.vhdx: 18.3 GB, a trim would free 2.6 GB
D:\VMs\Windows Server 2022.vhd: 9.5 GB, a trim would free 20.0 MB

8 images, 77.2 GB, a trim would free 5.1 GB

Trimming

:: trim every image in place
vdtrim batch --replace D:\VMs

:: write trimmed copies to another folder, originals untouched
vdtrim batch --output-dir E:\Trimmed D:\VMs

:: a scheduled task that keeps a folder of templates lean
vdtrim batch --replace --discard all --json C:\Logs\vdtrim.json D:\Templates

The images are trimmed one after another. An image that is declined or fails does not stop the run: its reason is printed and the next image follows, so a machine that happens to be running is simply skipped as in use and picked up the next time. With --output-dir each copy keeps the name and format of its original. The options --discard, --zero-free, --no-verify, --json and --progress work as for trim.

Before trimming, batch compares the space the results need with what is free. Images for which there is clearly no room are declined and the rest are trimmed; when space is merely tight, a warning is printed.

Recovering after an interruption

If a --replace run was killed or the computer lost power in the middle of it, files may be left beside the image. vdtrim recover image puts the disk back in order: depending on how far the trim had got, the original comes back or the verified trimmed disk is put in place. The command says which, and needs no licence.

Exit codes

Code Meaning
0 Success.
1 Declined: an image could not be trimmed safely, or there was nothing to gain. The image is unchanged. Batch returns the highest code among its images.
2 Error, such as a file that cannot be read or written.
3 The command line was not understood.
4 Trimming was asked for and no licence is installed.
5 The installed licence is no longer valid.

JSON report

--json file on analyse, trim and batch writes everything the command found as a JSON document; --json - prints it to standard output in place of the text. File → Save Report in the application window saves the same document for the images in its list. All sizes are in bytes, and the values are fixed identifiers that do not change with the language of the window.

{
  "schema" : 1,
  "product" : "SoftPerfect Virtual Disk Trim",
  "version" : "1.0",
  "generated" : "2026-10-08T02:45:53Z",
  "images" : [
    {
      "file" : "D:\\VMs\\openSUSE Tumbleweed.vmdk",
      "outcome" : "ok",
      "status" : "ready",
      "leftover" : "none",
      "analysis" : {
        "fileSize" : 783941632,
        "sizeOnDisk" : 783941632,
        "format" : "vmdk",
        "layout" : "single",
        "files" : [ "D:\\VMs\\openSUSE Tumbleweed.vmdk" ],
        "virtualSize" : 25769803776,
        "partitioning" : "gpt",
        "volumes" : [ ... ],
        "reclaimable" : { ... }
      },
      "trim" : {
        "status" : "saved",
        "output" : "E:\\Trimmed\\openSUSE Tumbleweed.vhdx",
        "outputFormat" : "vhdx",
        "outputSize" : 774897664,
        "sourceSize" : 783941632,
        "saved" : 9043968,
        "verified" : true
      }
    }
  ]
}

The example is shortened. The fields a script most often needs:

Field Content
images[].outcome ok, declined or failed.
images[].reason, reasonKind For an image declined or failed at analysis (a trim that was declined or failed carries the same two fields under trim): the explanation as an English sentence, and its kind as an identifier such as inUse, unclean, snapshot or unsupported.
images[].leftover none, or what an interrupted trim left beside the image.
analysis.volumes[] Each partition and volume: type, position, file system, label, total, used and free bytes, and any page, swap or hibernation files found. A volume that is not trimmed carries its own reason and reasonKind.
analysis.reclaimable What a trim would free, at the image’s own block size and at 1 MB blocks, with and without discarding page, swap and hibernation files.
trim.output, outputFiles The output and, for a disk of several files, every file it consists of.
trim.saved How many bytes smaller the output is than the source, by the room each takes on the disk.
trim.verified Whether the output was compared with the source.