How can I check the size of a file in a Windows batch script?
Asked Answered
P

14

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
Parament answered 29/7, 2009 at 11:40 Comment(0)
U
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
)
Uncleanly answered 29/7, 2009 at 12:15 Comment(5)
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 workingPanama
@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 ...Uncleanly
Hi @Uncleanly 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.Rehabilitation
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.Tarsier
Never mind... it doesn't even work to write it into a variable for me for an existing file...Tarsier
F
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
Flexuous answered 24/4, 2015 at 11:43 Comment(0)
P
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
Pulmonate answered 29/7, 2009 at 12:8 Comment(0)
I
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
Inweave answered 4/6, 2014 at 18:42 Comment(3)
there's no function and :eof in DOS. Those are features of Windows cmd.exe. They're completely differentOn
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.Blackcock
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...Moxley
H
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.

Hypodermic answered 29/7, 2009 at 12:7 Comment(0)
D
7

Another example

  FOR %I in (file1.txt) do @ECHO %~zI
Destruction answered 20/5, 2014 at 6:2 Comment(1)
I think you need %I to be %%I and %~zI to be %%~zI for it to work in a batch fileMetaphosphate
L
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.

Luminescent answered 29/7, 2009 at 12:6 Comment(0)
B
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

Backpack answered 13/10, 2016 at 10:45 Comment(0)
B
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.

Bookmaker answered 25/7, 2013 at 16:42 Comment(0)
D
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.

Danilodanio answered 24/7, 2014 at 3:49 Comment(0)
M
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
Medea answered 14/7, 2013 at 20:6 Comment(0)
G
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 !

Greg answered 26/1, 2015 at 15:7 Comment(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.Flexuous
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.Corabelle
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).Oblique
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).Oblique
We can get around the INT32 issue by doing it as a padded string comparison.Flexuous
A
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.

Ashtray answered 4/8, 2020 at 4:28 Comment(0)
U
-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.

Unification answered 29/7, 2009 at 11:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.