How to Get Size of a File in Bytes in Batch Script
A common task in automation and file management scripts is to determine the size of a file. You might need to verify a download, check log file growth, ensure a file is not empty before processing it, or simply report on disk usage. While there are several ways to do this in Windows Batch, the most direct, efficient, and native method is by using a special modifier within a FOR
loop.
This guide will provide a thorough explanation of the %%~z
FOR
variable modifier, demonstrate its use, show how to build it into a robust and reusable subroutine for your own scripts, and explain how it gracefully handles common issues like file paths with spaces or files that don't exist.
Why Get a File's Size in a Batch Script?
Determining a file's size programmatically is crucial for many scripting tasks:
- Verification: Confirming that a file copy or download has completed and is not zero bytes.
- Logging: Recording the size of log files or data archives as part of a process.
- Conditional Logic: Only processing files that are within a certain size range.
- Reporting: Creating simple inventory or status reports that include file sizes.
The Core Technique: The %%~z
FOR
Variable Modifier
The FOR
command in Batch has a set of powerful modifiers (also called "parameter expansions") that can extract specific pieces of information about a file. The one we need for size is ~z
.
When a FOR
loop variable (e.g., %%A
) represents a file, %%~zA
expands to the size of that file in bytes.
Basic Usage and Syntax
@ECHO OFF
SET "filename=C:\Windows\System32\notepad.exe"
REM The FOR loop iterates over the single item in the set, which is our filename.
REM %%F will hold the full filename.
REM %%~zF will expand to its size in bytes.
FOR %%F IN ("%filename%") DO ECHO Size of "%%F" is %%~zF bytes.
Output:
Size of "C:\Windows\System32\notepad.exe" is 213504 bytes.
Your actual size for notepad.exe
may vary depending on your Windows version.
It is critical to enclose the filename/path in double quotes within the FOR
loop's set: FOR %%F IN ("%filename%")
. This ensures that file paths containing spaces are treated as a single item and parsed correctly.
Without the quotes, a path like "C:\Program Files\App\file.txt"
would be seen as three separate items by the FOR
loop.
A Practical, Reusable Subroutine (:GetFileSize
)
For real-world scripting, it's best to encapsulate this logic in a callable subroutine. The following script provides a :GetFileSize
subroutine that takes a filename as input and "returns" the size in a variable specified by the caller.
The Script with a Reusable Subroutine
@ECHO OFF
SETLOCAL
SET "myFile=C:\Windows\explorer.exe"
REM --- Example 1: Call the subroutine and get the size back ---
CALL :GetFileSize "%myFile%" fileSizeInBytes
IF DEFINED fileSizeInBytes (
ECHO The file size of "%myFile%" is %fileSizeInBytes% bytes.
) ELSE (
ECHO Could not find the file: "%myFile%"
)
ECHO(
REM --- Example 2: Handling a file that does not exist ---
CALL :GetFileSize "C:\path\to\a\non_existent_file.txt" fileSizeInBytes
IF DEFINED fileSizeInBytes (
ECHO This line should not be printed.
) ELSE (
ECHO The subroutine correctly reported the file does not exist.
)
ECHO(
GOTO :EOF
REM ======================================================================
:GetFileSize FilePath [ReturnVar]
:: Gets the size of a specified file in bytes.
:: %~1 [in] - The full path to the file to check.
:: %~2 [out] - Optional. The name of the variable to store the file size in.
:: The return variable will be undefined if the file does not exist.
:: If ReturnVar is not specified, the size is ECHOed to the console.
SETLOCAL
SET "filePath=%~1"
SET "fileSize="
REM Check if the file exists to run the FOR loop only when necessary.
IF EXIST "%filePath%" (
FOR %%F IN ("%filePath%") DO SET "fileSize=%%~zF"
)
(
ENDLOCAL
IF "%~2" NEQ "" (SET %~2=%fileSize%) ELSE (ECHO %fileSize%)
)
EXIT /B
Breakdown of the :GetFileSize
Subroutine
SETLOCAL
/ENDLOCAL
: These commands create a localized scope for variables inside the subroutine, preventing unintended side effects on the main script's environment.SET "filePath=%~1"
: Safely captures the first argument (the file path).%~1
removes any surrounding quotes from the argument.IF EXIST "%filePath%"
: This is a crucial robustness check. It ensures theFOR
loop only attempts to run on a file that actually exists, preventing wasted processing.FOR %%F IN ("%filePath%") DO SET "fileSize=%%~zF"
: This is the core logic. It runs the loop (which will only iterate once for a single file) and sets the localfileSize
variable to the result of%%~zF
.(ENDLOCAL & SET %~2=%fileSize%)
: This is a standard batch technique to "return" a value from a subroutine. It ends theSETLOCAL
session and then, on the same logical line, sets the variable named by the second argument (%~2
) in the parent script's context. If no second argument is given, it simplyECHO
s the size.
How to Use the Subroutine
REM Store the size of mylog.txt in the variable 'logSize'
CALL :GetFileSize "C:\logs\mylog.txt" logSize
REM Check if the file existed and its size was retrieved
IF NOT DEFINED logSize (
ECHO C:\logs\mylog.txt not found.
) ELSE (
ECHO The log file is %logSize% bytes.
IF %logSize% GTR 1048576 ECHO Warning: Log file is larger than 1MB.
)
Handling "File Not Found" Scenarios
A great feature of using the FOR
command for this purpose is its graceful handling of missing files. If you provide a path to a file that does not exist, the FOR
loop simply does not iterate. It does not produce an error.
@ECHO OFF
REM This will not produce an error or any output.
FOR %%A IN ("C:\path\to\a\non_existent_file.txt") DO ECHO Size is %%~zA
ECHO Script continues without interruption.
This is why checking IF DEFINED
on the return variable from our :GetFileSize
subroutine is a reliable way to know if the file was found and its size was successfully retrieved.
Why This Method is Superior to DIR
Parsing
Another common method to get file size is to parse the output of the DIR
command.
REM --- Old, less reliable method ---
FOR /F "tokens=3,4" %%A IN ('dir "myfile.txt" ^| find "myfile.txt"') DO ECHO Size is %%A bytes
This method is fragile because:
- The position of the file size (
token=3
) can change based on date/time format settings. - It requires complex parsing and is much slower.
- The
dir
command format can vary between different Windows versions or language settings.
The %%~z
modifier is direct, fast, and locale-independent, making it the superior choice.
Conclusion
Using the FOR
command with the %%~z
modifier is the most efficient, reliable, and native way to get a file's size in bytes within a Windows Batch script. It is faster and more robust than parsing the output of DIR
.
By encapsulating this simple yet powerful command in a reusable subroutine like :GetFileSize
, you can create a clean and powerful tool for all your file management and automation scripts.