How to reserve disk space to save yourself from a world of pain

How to reserve disk space to save yourself from a world of pain

Tom Chantler

Summary

Running out of disk space is always annoying, but it's especially bad if it happens when you're in the middle of something important. You find yourself needing to free up some space quickly, often when the computer is so busy with an IO-intensive task that there's very little you can do.

In this article I present an easy way to reserve disk space via a simple batch file, either interactively or by using command line parameters. There are also a couple of quite useful batch file tricks as well, such as checking you're running as an administrator.

The files it creates are named EmptyFile_xxxMB_nnn.dat, so if you create 3 250MB files, they'd be called:

EmptyFile_250MB_001.dat
EmptyFile_250MB_002.dat
EmptyFile_250MB_003.dat

As usual, everything is in GitHub.

https://github.com/TomChantler/ReserveDiskSpace

You can use the batch file on its own, but I've also included a way to install it as well. To do that, download the files, right-click on Install.bat and choose Run as administrator...[1]

Background

In these days of cheap computer storage and elastic provisioning and so on you could be forgiven for thinking that there's never an excuse for running out of space. However, in the real world it doesn't always work like that, especially when you're using your own hardware. After I'd run out of space on my desktop machine[2] once too often, I decided to solve the problem by reserving some space in advance and then having that space available to release when required, thus buying myself vital time to obtain more space permanently, either by removing stuff or adding hard drives. Think of it like emergency credit (anyone who's ever had a prepay electricity meter will know exactly what I'm talking about).

The batch file can either be used interactively or it can be called with command line parameters, which makes it easy to build it into a provisioning script. Alternatively, you could just buy a bigger disk in the first place and come up with a sensible strategy to manage your remaining space, but I've tried this in the past and I still seem to run out of space occasionally.

Before we go any further, the super-observant amongst you may have noticed the date of this post. Coupled with the somewhat tongue-in-cheek nature of this article, you could be forgiven for thinking that this is a (not particularly) funny April Fools' joke. It isn't. It's a real thing. The batch file tricks will come in handy in all sorts of situations and I have genuinely use this reserving-disk-space-up-front strategy in the past to great effect.

The files

There are three files to download:

  • ReserveDiskSpace.bat - this creates the empty files.
  • Install.bat - copies the other file to the right place (you don't necessarily need to do this).
  • SparseExamples.bat - creates some sparse files (this is not part of the space reservation strategy and is explained later on).

Each of the batch files has comments to explain what's going on. If you want a great reference for the Windows Command Line, I can recommend SS64.

The batch file - ReserveDiskSpace.bat

The batch file is split into six main sections. I have given them fairly self-explanatory names:

  • CheckIfAnyParametersPassedIn - If you have passed in any parameters, it does some simple validation and then either goes straight to the UseParams section or runs interactively by going to GetFileSize.
  • GetFileSize - prompts the user to choose a file size when running interactively. Goes to one of Choice1 - 5.
  • Choice1 - 5 - Called by GetFileSize. Sets the chosen file size and goes to GetNumberOfFiles.
  • GetNumberOfFiles - prompts the user to choose how many files they want to create, dynamically showing them the total space that will reserve. Goes to MakeFiles.
  • UseParams - if the user passed in valid command-line parameters they are used here. Sets file size, number of files and checks that the destination directory either already exists or can be created.
  • MakeFiles - creates the empty files.

The most important thing in the batch file is the creation of the empty files which is done via fsutil file createnew a bit like this:

fsutil file createnew C:\1GB.dat 1073741824

Usage

You can either run ReserveDiskSpace.bat interactively, or with parameters.

Running interactively

If you run ReserveDiskSpace.bat interactively, you are first prompted for the size of each file you want to create and are then prompted for the number of files. Notice that it works out the amount of disk space you're going to reserve.

Interactive usage

Running with parameters

If you're using it in another script, then you can do it like this:

ReserveDiskSpace sizeOfEachFileinMB numberOfFiles [path]

e.g.

ReserveDiskSpace 1024 6 will make six 1GB files in the current working directory.

ReserveDiskSpace 100 10 D:\temp will make ten 100MB files in the temp directory on the D drive (if the D drive exists, has sufficient space and the batch file is running with sufficient permissions).

Parameterised usage

NOTE: Remember to use double quotes around the path if it contains any spaces.
e.g. ReserveDiskSpace 100 10 "C:\A folder containing spaces"

The installation batch file - Install.bat

The installation file does three things:

  • First it checks that it's running with Administrator permissions.
  • Then it copies ReserveDiskSpace.bat to the %ProgramFiles(x86)%/TomSSL directory (which it creates if necessary).
  • Finally it adds a system-wide environment variable TomSSL (accessed via %TomSSL% in the batch file) which contains the path %ProgramFiles(x86)%/TomSSL.

Whilst the ReserveDiskSpace.bat batch file itself is fairly simple[3], trying to install its location into your path as part of a separate batch file isn't. This is due to the truncation-at-1024-characters rule, of which you can see a brief description and for which there are some some suggested workarounds here. One of the better ways round the problem is to use PowerShell, but doing so would decrease the accessibility of this script somewhat, so it's probably best to admit defeat and not to tamper with your PATH environment variable.

Instead, you could add the %ProgramFiles(x86)%/TomSSL path to a new system-wide environment variable and then add that to the path in any script which calls the batch file.

Or you could just call the batch file directly by providing its complete path when you use it.

At this point, it's probably worth pointing out that the real point of the Install.bat file is to show you how to do the things it's doing. In practice you are not very likely to want to install ReserveDiskSpace.bat as you probably won't be using it very often (about once per disk).

Check for administrative permissions in a batch file

Some batch files, such as the Install.bat here, will only work if they are run with Administrative permissions. You can check that you are running with administrative permissions like this:

net session >nul 2>&1
if %errorlevel% == 0 (
    echo Running as administrator.
) else (
    echo Sorry, you need to run this as an administrator.
    goto :eof
)

This is explained in some detail at https://stackoverflow.com/questions/4051883/batch-script-how-to-check-for-admin-rights

The difference between set and setx

setx is used to create or modify environment variables at the machine or user level. It sets these variables permanently and, crucially, not in the current scope. This means you need to quit your current command window and open a new one to use the new values.

set is the opposite. It sets the values temporarily and only in the current scope (i.e. the current command window).

Setx provides the only command-line or programmatic way to directly and permanently set system environment values. System environment variables are manually configurable through Control Panel or through a registry editor. The set command, which is internal to the command interpreter (Cmd.exe), sets user environment variables for the current console window only.

Taken verbatim from setx documentation on TechNet

In Install.bat, I use setx TomSSL "%%ProgramFiles(x86)%%\TomSSL" /m (the double % being needed because it's part of a batch file) to create a permanent %TomSSL% environment variable. Then I can use set to use it in another batch file.

setx ... /m writes to HKEY_LOCAL_MACHINE

setx ... writes to HKEY_CURRENT_USER

To set the path locally we need to do this:
set path=%PATH%;%TomSSL% (with no quotes) having run Install.bat as an admin.

You can check it worked like this:

C:\>echo %TomSSL%

Check TomSSL path

e.g. as part of a larger batch file, you could set the path at the top and then ReserveDiskSpace without the full path. Or just use "%TomSSL%\ReserveDiskSpace" (with double quotes) to use the system-wide environment variable in your batch file without using a local set command first.

A note about sparse files

Whilst researching this article, I read a number of articles which were completely wrong, including suggestions that the fsutil file createnew ... command creates sparse files. This is not the case.

Sparse files do not actually have disk space allocated to them until it is needed. In practice this means that, until the file is actually full, a sparse file takes up less space on disk than the file size suggests.

In this case, we specifically don't want to create a sparse file as the whole purpose of what we are doing is to reserve disk space.

The way to create a sparse file is first to create a file as normal, then set the sparse flag, then tell it which bytes are to be sparsely allocated (i.e. not to be allocated to disk). This means that, at the point of creation, you do actually need to have sufficient space for the whole file on your disk, although you can free that space up again immediately.

This is probably best illustrated with a couple of examples.

First the syntax for the creation of a simple 1GB sparse file. In the final line, the two numbers represent the start offset and length (both in bytes) of the sparse region, so in this case we are marking the entire file as sparse.

fsutil file createnew C:\1GB.dat 1073741824
fsutil sparse setflag C:\1GB.dat
fsutil sparse setrange C:\1GB.dat 0 1073741824

For the second example (which is included in the GitHub repo and for which we need an initial 10GB of disk space), ostensibly we will create 100GB of files, but in fact they will take up zero space once we've finished.

SparseExample.bat

@echo off
REM By Tom Chantler - https://tomssl.com/2016/04/01/how-to-reserve-disk-space-to-save-yourself-from-a-world-of-pain
REM 100GB of files takes up no disk space
:CheckIfRunningAsAdministrator
net session >nul 2>&1
if %errorlevel% == 0 (
    echo Running as administrator.
) else (
    echo Sorry, you need to run this as an Administrator.
    goto End
)
:CreateSparseFiles
setlocal EnableDelayedExpansion
for /l %%i in (1,1,10) DO (
    set "%%i=0000%%i"
    fsutil file createnew C:\10GB_!%%i:~-3!.dat 10737418240
    fsutil sparse setflag C:\10GB_!%%i:~-3!.dat
    fsutil sparse setrange C:\10GB_!%%i:~-3!.dat 0 10737418240
)
:End
echo Done.

Notice that writing 100GB of sparse files didn't really take up any space.

Sparse Files Disk Space

Sparse Files Properties

I've been trying to think of a good reason why you might want to do this, but so far the only thing I can come up with is that they are a way of setting a maximum size for an expanding file, such as a virtual hard disk for a virtual machine. If you know better, please let me know in the comments.

Conclusion

The best way I've found to ensure that I don't run out of space on my hard drives is to reserve some in advance with one or more dummy files. This way, when it seems that I have run out of space, I can delete some of these placeholder files and buy myself enough time to address the issue properly.

To make this simple process even easier, I've created a batch file to automate it. You can download it from https://github.com/TomChantler/ReserveDiskSpace.

Whilst this solution might seem to be overkill, some of the tricks employed in the batch file might well be of use in other situations.



  1. And if you don't run it as an administrator, it'll know and will complain by using the "running as an administrator" trick I just alluded to. ↩︎

  2. It's technically a laptop, but is actually the "rather expensive flat desktop machine with an integral hinged screen" that I referenced in my post about fixing the WiFi on your Surface Pro 3. ↩︎

  3. Well, it's somewhat simple. At least it's reasonably clearly laid out. ↩︎