75

I want to have a batch file which checks what the filesize is of a file.

If it is bigger than %somany% kbytes, it should redirect with GOTO to somewhere else.

Example:

[check for filesize]
IF %file% [filesize thing Bigger than] GOTO No
echo Great! Your filesize is smaller than %somany% kbytes.
pause
exit
:no
echo Um... You have a big filesize.
pause
exit

14 Answers 14

107

If the file name is used as a parameter to the batch file, all you need is %~z1 (1 means first parameter)

If the file name is not a parameter, you can do something like:

@echo off
setlocal
set file="test.cmd"
set maxbytesize=1000

FOR /F "usebackq" %%A IN ('%file%') DO set size=%%~zA

if %size% LSS %maxbytesize% (
    echo.File is ^< %maxbytesize% bytes
) ELSE (
    echo.File is ^>= %maxbytesize% bytes
)
5
  • 8
    Can you explain how the "usebackq" option helps? It doesn't seem to have anything to do with file size, but if I remove it, it stops working
    – JoelFan
    Commented Jun 3, 2010 at 15:27
  • 14
    @JoelFan: Without usebackq, the ' quote means command and not string (Run FOR /? for the details) Another alternative (To better deal with spaces in filenames) is to use: FOR /F "tokens=*" %%A IN ("%file%") DO ...
    – Anders
    Commented Jun 3, 2010 at 17:33
  • Hi @Anders Can you let me know how I can do the same when I have multiple files in a sequence. Like I want to set if my file is less than 2kb then move it to a diff folder?. My result should test each file in the path and validate. Commented Dec 30, 2015 at 8:30
  • Side note: you should check if the file exists, before. Otherwise the file size will simply be an empty string... took me a while to notice. Commented Jun 21, 2018 at 15:18
  • Never mind... it doesn't even work to write it into a variable for me for an existing file... Commented Jun 21, 2018 at 15:42
27

I like @Anders answer because the explanation of the %~z1 secret sauce. However, as pointed out, that only works when the filename is passed as the first parameter to the batch file.

@Anders worked around this by using FOR, which, is a great 1-liner fix to the problem, but, it's somewhat harder to read.

Instead, we can go back to a simpler answer with %~z1 by using CALL. If you have a filename stored in an environment variable it will become %1 if you use it as a parameter to a routine in your batch file:

@echo off
setlocal
set file=test.cmd
set maxbytesize=1000

call :setsize %file%

if %size% lss %maxbytesize% (
    echo File is less than %maxbytesize% bytes
) else (
    echo File is greater than or equal %maxbytesize% bytes
)
goto :eof

:setsize
set size=%~z1
goto :eof

I've been curious about J. Bouvrie's concern regarding 32-bit limitations. It appears he is talking about an issue with using LSS not on the filesize logic itself. To deal with J. Bouvrie's concern, I've rewritten the solution to use a padded string comparison:

@echo on
setlocal
set file=test.cmd
set maxbytesize=1000

call :setsize %file%

set checksize=00000000000000000000%size%
set checkmaxbytesize=00000000000000000000%maxbytesize%
if "%checksize:~-20%" lss "%checkmaxbytesize:~-20%" (
    echo File is less than %maxbytesize% bytes
) else (
    echo File is greater than or equal %maxbytesize% bytes
)
goto :eof

:setsize
set size=%~z1
goto :eof
0
11

%~z1 expands to the size of the first argument to the batch file. See

C:\> call /?

and

C:\> if /?

Simple example:

@ECHO OFF
SET SIZELIMIT=1000
SET FILESIZE=%~z1

IF %FILESIZE% GTR %SIZELIMIT% Goto No

ECHO Great! Your filesize is smaller than %SIZELIMIT% kbytes.
PAUSE
GOTO :EOF

:No
ECHO Um ... You have a big filesize.
PAUSE
GOTO :EOF
0
11

I prefer to use a DOS function. Feels cleaner to me.

SET SIZELIMIT=1000
CALL :FileSize %1 FileSize
IF %FileSize% GTR %SIZELIMIT% Echo Large file

GOTO :EOF

:FileSize
SET %~2=%~z1

GOTO :EOF
3
  • there's no function and :eof in DOS. Those are features of Windows cmd.exe. They're completely different
    – phuclv
    Commented Jan 22, 2018 at 12:22
  • 2
    Except for the nit about not being DOS. This is the cleanest solution. using call :label to get a numbered argument that can be used.
    – NiKiZe
    Commented Jul 31, 2018 at 9:11
  • FYI I inadvertently had SET FileSize=0 at top of my script and this breaks things. Possibly makes an outer scope variable that remains unchanged when "function call" returns. Hope it helps others...
    – Razzle
    Commented Jan 17, 2022 at 20:46
10

If your %file% is an input parameter, you may use %~zN, where N is the number of the parameter.

E.g. a test.bat containing

@echo %~z1

Will display the size of the first parameter, so if you use "test myFile.txt" it will display the size of the corresponding file.

7

Another example

  FOR %I in (file1.txt) do @ECHO %~zI
1
  • I think you need %I to be %%I and %~zI to be %%~zI for it to work in a batch file
    – ZiyadCodes
    Commented Mar 16, 2023 at 11:29
4

As usual, VBScript is available for you to use.....

Set objFS = CreateObject("Scripting.FileSystemObject")
Set wshArgs = WScript.Arguments
strFile = wshArgs(0)
WScript.Echo objFS.GetFile(strFile).Size & " bytes"

Save as filesize.vbs and enter on the command-line:

C:\test>cscript /nologo filesize.vbs file.txt
79 bytes

Use a for loop (in batch) to get the return result.

4

After a few "try and test" iterations I've found a way (still not present here) to get size of file in cycle variable (not a command line parameter):

for %%i in (*.txt) do (
    echo %%~zi
)

~z gets the file size of the file

2

This was my solution for evaluating file sizes without using VB/perl/etc. and sticking with native windows shell commands:

FOR /F "tokens=4 delims= " %%i in ('dir /-C %temp% ^| find /i "filename.txt"') do (  
    IF %%i GTR 1000000 (  
        echo filename.txt filesize is greater than 1000000  
    ) ELSE (  
        echo filename.txt filesize is less than 1000000  
    )
)  

Not the cleanest solution, but it gets the job done.

2

Create a one line batch file GetFileSize.bat containing

GetFileSize=%~z1

then call it

call GetFileSize  myfile.txt
if (%GetFileSize) == ()     goto No_File
if (%GetFileSize) == (0)    goto No_Data
if (%GetFileSize) GTR 1000  goto Too_Much_Data
rem Etc.

You can even create your test file on the fly to eliminate the pesky required file, note the double percent in the echo statement:

echo set GetFileSize=%%~z1 > %temp%\GetFileSize.bat
call %temp%\GetFileSize  myfile.txt
if (%GetFileSize) GTR 1000  goto Too_Much_Data
rem etc

This latter solution is antispaghetti. So nice. However, more disk writes. Check use count.

1

Just saw this old question looking to see if Windows had something built in. The ~z thing is something I didn't know about, but not applicable for me. I ended up with a Perl one-liner:

@echo off

set yourfile=output.txt
set maxsize=10000

perl -e "-s $ENV{yourfile} > $ENV{maxsize} ? exit 1 : exit 0"
rem if %errorlevel%. equ 1. goto abort
if errorlevel 1 goto abort

echo OK!
exit /b 0

:abort
echo Bad!
exit /b 1
0

Important to note is the INT32 limit of Batch: 'Invalid number. Numbers are limited to 32-bits of precision.'

Try the following statements:

IF 2147483647 GTR 2147483646 echo A is greater than B (will be TRUE)
IF 2147483648 GTR 2147483647 echo A is greater than B (will be FALSE!)

Any number greater than the max INT32 value will BREAK THE SCRIPT! Seeing as filesize is measured in bytes, the scripts will support a maximum filesize of about 255.9999997615814 MB !

5
  • This is incorrect. I created a 5 GB file and was able to read it's file size using %~z1 and it reported 5056590344. Commented Jul 18, 2015 at 10:43
  • 1
    That's because it is still a string, not converted to a number. Try to do a comparison, or arithmetic with Set /A, and anything to larger than 2 GB will fail.
    – Bilbo
    Commented Jul 27, 2017 at 2:27
  • When converting NTFS to FAT32 it is important to determine which files are over the 4GB limit. Though Windows explorer allows searching "size:>4GB", I prefer having a text-output of results. Indeed, Windows 10 still has the INT32 CLI and BATCH limit 2^31. With logic: "Show me all files on my F: drive that need addressing:" - @for /f "tokens=*" %F in ('dir /s /b /a:-d f:\') do @IF %~zF geq 4294967296 ECHO %F >> FindFilesTooLargeForFAT32.txt. Output is files over 2GB (not 256MB). 2^31 = 32bit = 2,147,483,648 = 2GB (technically GiB gibibyte 1024^3 * 2). Commented Jun 2, 2019 at 17:33
  • Work-around is: explorer filtered view (i.e.: size:>4GB), Ctrl+A, Shift r-click, Copy As Path, Paste in Notepad++, TextFX Tools Sort Ascending (since the Copy As Path doesn't mirror order shown in UI). Commented Jun 2, 2019 at 18:03
  • We can get around the INT32 issue by doing it as a padded string comparison. Commented Jul 10, 2019 at 5:10
0

You'll need two things.

filesize.bat 

@echo off
echo %~z1

And then what you're actually trying to size up.

Copy a file only if it's larger than zero / copy only a non-zero file

for /f %i in ('filesize filesize.bat') do set z=%i
if %z% gtr 0 ( copy filesize.bat noodles.bat )

I found this thread and it was almost what I needed, I tried a bunch of different things - this was mildly frustrating because robocopy looked to have /min:1 but got ALL bunged up because I wanted to rename the file in transit which made me have to use @#$!! batch script.

0
-6

Just an idea:

You may get the filesize by running command "dir":

>dir thing

Then again it returns so many things.

Maybe you can get it from there if you look for it.

But I am not sure.

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