Page 1 of 2
Help with File Size Calculations
Posted: 12 Jan 2014 13:24
by julesverne
Hi all, I found this cool bat code to parse out larger than 32 byte numbers.
http://ss64.org/viewtopic.php?id=288#p884 It takes a file size number like.. 999999999999999999999999999999 and turns it in TB GB MB KB B
What I'd like to do is take any file, no matter what size. have it give me the size output using the script the link has. Then take the total disk space available on a drive using the above method. Then.. subtract the file size output from the total diskspace output to see if it has enough free space to copy. I like this method cause I think it's pretty accurate down to the byte.
I'm not sure how to do this and I imagine if I did figure it out it would be convoluted code that would make it slower than it needs to be.
Thanks in advance!
Jules
Re: Help with File Size Calculations
Posted: 12 Jan 2014 16:01
by Aacini
The code at the indicated link does
not manage big numbers; it will fail if the parameter is a number larger than 32-bits.
I got the program at
this post and modified it in order to convert an unlimited size decimal number into a
base 1024 number (instead of a binary one). This way, the result is the equivalent number of Bytes + KB + MB + GB + TB + etc. of the decimal number. The result is given as an array of factors that is useful for compare a pair of numbers, for example, but that may be easily converted to a standard message.
EDIT: Small bug fixed. I also added an optional second parameter with the name of the array that receive the result.
Code: Select all
@echo off
setlocal EnableDelayedExpansion
rem DecimalToPowerOf1024.bat bigNumber [arrayName]
rem Decimal to power-of-1024 base conversion of an unlimited size decimal number
rem Antonio Perez Ayala
rem Get the name of the array, if any
set power=PowerOf1024
if "%~2" neq "" set "power=%~2"
rem Divide the number in 9-digits groups, eliminating left zeros in each group
set number=%1
set groups=0
:nextGroup
set group=%number:~-9%
for /L %%a in (1,1,8) do if "!group:~0,1!" equ "0" set group=!group:~1!
set /A groups+=1
set group[%groups%]=%group%
set number=%number:~0,-9%
if defined number goto nextGroup
rem Convert the 9-digits groups to power-of-1024 values
set /A bitPos=0, %power%=0, %power%[0]=0
:nextBinaryDigit
rem Divide the 9-digits groups by 2
set carry=0
for /L %%i in (%groups%,-1,1) do (
set /A term=carry*1000000000+group[%%i], group[%%i]=term/2, carry=term%%2
)
rem Insert remainder in current PowerOf1024 value, in right-to-left order
set /A "%power%[!%power%!]+=carry<<bitPos, bitPos+=1"
rem If current PowerOf1024 value completed: pass to next one
if %bitPos% equ 10 set /A bitPos=0, %power%+=1 & set %power%[!%power%!]=0
rem If last (most significant) group was completely converted: eliminate it
if !group[%groups%]! equ 0 set /A groups-=1
rem And pass to convert the rest of 9-digits groups
if %groups% gtr 0 goto nextBinaryDigit
for %%p in (!%power%!) do if !%power%[%%p]! equ 0 set "%power%[%%p]=" & set /A %power%-=1
set %power%
Antonio
Re: Help with File Size Calculations
Posted: 12 Jan 2014 16:48
by julesverne
So.. Can you please help me to understand the output a little?
H:\TEST>set $filename="C:\Users\xxx\Videos\movie\VIDEO_TS\all.vob"
H:\TEST>for %F in ("C:\Users\xxx\Videos\movie\VIDEO_TS\all.vob") do set "$size=%~zF"
H:\TEST>set "$size=1491345408"
H:\TEST>CALL "H:\TEST\filesizecompare.bat" 1491345408
Press any key to continue . . .
power=2
PowerOf1024[0]=513
PowerOf1024[1]=597
PowerOf1024[2]=468
Press any key to continue . . .
Re: Help with File Size Calculations
Posted: 12 Jan 2014 17:19
by julesverne
Also, how would i use this output to compare against another? i.e. filesize compared to available drive space.
Re: Help with File Size Calculations
Posted: 12 Jan 2014 18:39
by Aacini
The original code had a small bug!
Copy the code above again, please...
Code: Select all
C:\> DecimalToPowerOf1024.bat 1491345408
PowerOf1024=3
PowerOf1024[0]=0
PowerOf1024[1]=264
PowerOf1024[2]=398
PowerOf1024[3]=1
Previous result indicate that the decimal number 1491345408 is equal to 0 Bytes + 264 Kb + 398 Mb + 1 Gb.
I added an optional second parameter that define the name of the variables (last index and array) that receive the result, so you may directly store the result in different variables in order to compare they. For example:
Code: Select all
set filesize=value of filesize
call :DecimalToPowerOf1024 %filesize% file
set availableSpace=value of available space
call :DecimalToPowerOf1024 %availableSpace% drive
rem Test if availableSpace in drive is greater than filesize:
rem If there are more groups of numbers in drive than in file
if %drive% gtr %file% goto enoughSpace
rem If there are the same groups of numbers and drive number is greater than file number
if %drive% equ %file% if !drive[%drive%]! gtr !file[%file%]! goto enoughSpace
echo Not enough space
Let me know if this solution works correctly
Antonio
Re: Help with File Size Calculations
Posted: 12 Jan 2014 19:49
by julesverne
Thanks for the clarification on how to read the output and code. Two issues are occurring now after putting the two codes you supplied together.
This is the code:
Code: Select all
@echo on
set file="C:\Users\xxx\Videos\movie\VIDEO_TS\all.vob"
set drive="%~d0"
for %%F in (%file%) do set "filesize=%%~zF"
for %%F in (%drive%) do set "availableSpace"=%%~zF"
call :DecimalToPowerOf1024 %filesize% %file%
call :DecimalToPowerOf1024 %availableSpace% %drive%
rem Test if availableSpace in drive is greater than filesize:
rem If there are more groups of numbers in drive than in file
if %drive% gtr %file% goto enoughSpace
rem If there are the same groups of numbers and drive number is greater than file number
if %drive% equ %file% if !drive[%drive%]! gtr !file[%file%]! goto enoughSpace
echo Not enough space
pause
:DecimalToPowerOf1024
setlocal EnableDelayedExpansion
rem DecimalToPowerOf1024.bat bigNumber [arrayName]
rem Decimal to power-of-1024 base conversion of an unlimited size decimal number
rem Antonio Perez Ayala
rem Get the name of the array, if any
set power=PowerOf1024
if "%~2" neq "" set "power=%~2"
rem Divide the number in 9-digits groups, eliminating left zeros in each group
set number=%1
set groups=0
:nextGroup
set group=%number:~-9%
for /L %%a in (1,1,8) do if "!group:~0,1!" equ "0" set group=!group:~1!
set /A groups+=1
set group[%groups%]=%group%
set number=%number:~0,-9%
if defined number goto nextGroup
rem Convert the 9-digits groups to power-of-1024 values
set /A bitPos=0, %power%=0, %power%[0]=0
:nextBinaryDigit
rem Divide the 9-digits groups by 2
set carry=0
for /L %%i in (%groups%,-1,1) do (
set /A term=carry*1000000000+group[%%i], group[%%i]=term/2, carry=term%%2
)
rem Insert remainder in current PowerOf1024 value, in right-to-left order
set /A "%power%[!%power%!]+=carry<<bitPos, bitPos+=1"
rem If current PowerOf1024 value completed: pass to next one
if %bitPos% equ 10 set /A bitPos=0, %power%+=1 & set %power%[!%power%!]=0
rem If last (most significant) group was completely converted: eliminate it
if !group[%groups%]! equ 0 set /A groups-=1
rem And pass to convert the rest of 9-digits groups
if %groups% gtr 0 goto nextBinaryDigit
for %%p in (!%power%!) do if !%power%[%%p]! equ 0 set "%power%[%%p]=" & set /A %power%-=1
set %power%
GOTO :EOF
This is the OUTPUT
Code: Select all
H:\TEST>set file="C:\Users\xxx\Videos\movie\VIDEO_TS\all.vob"
H:\TEST>set drive="H:"
H:\TEST>for %F in ("C:\Users\xxx\Videos\movie\VIDEO_TS\all.vob") do set "filesize=%~zF"
H:\TEST>set "filesize=1491345408"
H:\TEST>for %F in ("H:") do set "availableSpace"=%~zF"
H:\TEST>set "availableSpace"=4096"
H:\TEST>pause
Press any key to continue . . .
Issue #1. after i press a key I can see that it is saying "missing operator" EDIT: IT ERRORS AND EXITS OUT
Issue #2. is this bit of code at the top,
Code: Select all
for %%F in (%drive%) do set "availableSpace"=%%~zF"
Using that code the output says drive H: is 4096 which.. I don't really understand why, nor do i understand what that number is. The file size is correct using %~zF According to windows explorer properties it's 455 GB available space.
I don't know if it matters that I put both pieces of your code together in one bat file, which I feel is a bit better.
Re: Help with File Size Calculations
Posted: 13 Jan 2014 00:44
by foxidrive
This batch file can be passed a file such as:
CalcFilesize.bat "%userprofile%\Videos\movie\VIDEO_TS\all.vob"
and it will return
yes or
no in
%result% to tell you if there is enough space on the current drive for it.
It's not tested
Code: Select all
@echo off
set filesize=%~z1
for /f "tokens=3" %%a in ('dir /-p /-c ^|find " bytes free"') do set calc=%%a-%filesize%
echo %calc%
>"%temp%\VBS.vbs" echo Set fso = CreateObject("Scripting.FileSystemObject")
>>"%temp%\VBS.vbs" echo if (%calc%) ^> -1 then wscript.echo "yes" else wscript.echo "no"
for /f "delims=" %%a in ('cscript /nologo "%temp%\VBS.vbs"') do set "result=%%a"
del "%temp%\VBS.vbs"
echo %result%
Re: Help with File Size Calculations
Posted: 13 Jan 2014 11:44
by julesverne
This batch file can be passed a file such as: CalcFilesize.bat "%userprofile%\Videos\movie\VIDEO_TS\all.vob"
and it will return yes or no in %result% to tell you if there is enough space on the current drive for it.
It's not tested.
Hi Foxidrive, thanks! Unfortunately, the reason this won't work for me is the Windows 32 bit size limit. So Aacini came up with a way to manage the big numbers into groups. For instance I'll be using this bat to see if a file will fit onto a server (which will have a big number) or a TB external drive (which will also have a big number.
I had a couple issues with the last 2 bits of code Aacini came up with when I merged them together.
Issue #1. after i press a key I can see that it is saying "missing operator" EDIT: IT ERRORS AND EXITS OUT
Issue #2. is this bit of code at the top,
Code: Select all
for %%F in (%drive%) do set "availableSpace"=%%~zF"
Using that code the output says drive H: is 4096 which.. I don't really understand why, nor do i understand what that number is. The file size is correct using %~zF According to windows explorer properties it's 455 GB available space.
That last bit I quoted myself I realized doesn't sound very clear. Using that code the output says drive H: is 4096 using the standard %%~zF but looking at windows explorer properties it says the drive is 455 GB of available space.. so I don't understand where CMD is coming up with 4096 for %%~zF
Re: Help with File Size Calculations
Posted: 13 Jan 2014 18:58
by Endoro
You do not need VB nor math to compare big numbers in Batch:
Code: Select all
@ECHO OFF &SETLOCAL
if "%~1"=="" echo(Missing file name.&exit /b 1
if not exist "%~1" echo(File not found: "%~1".&exit /b 1
for /f %%a in ("%~1") do set "fileattrib=%%~aa"
if "%fileattrib:~0,1%"=="d" echo("%~1" is directory.&exit /b 1
set "filesize=%~z1"
if "%filesize%"=="0" echo("%~1": file size is zero.&exit /b 1
for /f "tokens=2delims=:" %%a in ('fsutil volume diskfree %cd:~0,2%') do for %%b in (%%~a) do set "diskfree=%%~b"
echo(File size: %filesize% byte(s) in "%~1"
echo(Disk free: %diskfree% byte(s) on %cd:~0,2%
set "prefix=000000000000000"
set "filecompare=%prefix%%filesize%"
set "filecompare=%filecompare:~-15%"
set "diskcompare=%prefix%%diskfree%"
set "diskcompare=%diskcompare:~-15%"
for /f "tokens=1*delims==" %%a in ('(set diskcompare^&set filecompare^) ^|sort') do set "result=%%b"
<nul set /p "=You can "
if "%result%"=="%diskcompare%" <nul set /p "=NOT "
echo(copy "%~1" to %cd:~0,2%
Re: Help with File Size Calculations
Posted: 13 Jan 2014 19:55
by penpen
Another possibility is, to use the 1.
http://en.wikipedia.org/wiki/Intercept_theorem to shorten the numbers:
Use |SA|:|SB|==|SC|:|SD| to scale the filesizes to smaller numbers.
For example the dir command may give you these sizes:
- HDD free space |SB| := 111,222,333,444
- file size |SD| := 888,777,666
In addition use a ratio of 1000 == |SA|:|SB|
Then you get as a results (in int32 values, a little rounding error):
- |SA|==111,222,333
- |SC|==888,777
As you see the ratios haven't changed.
penpen
PS: It is similar to Endoros solution (also based on the 1. IT), but he exceeded the digits, instead of shortening them.
Re: Help with File Size Calculations
Posted: 13 Jan 2014 21:09
by Aacini
@julesverne:
I assumed from your first post that you knew how to take the total disk space available on a drive and the size of a file, and that you asked for help in the comparison of big numbers...
Your guessing that "for %%F in (%~d0) do set "availableSpace=%%~zF" return the available space in a drive have no base. Why this method could not return the occupied or total space in a drive? I have not found a single reference on the meaning of "%%~z" modifier when it is used on a drive; in my computer it returns 28672 (?). You may get the available space in a drive from the third token in the last line of DIR command:
Code: Select all
for /F "tokens=3" %%F in ('dir /-C "%~N0.bat"') do set "availableSpace=%%F"
Note also that your code have several small errors:
- for %%F ... set "availableSpace"=%%~zF" command have an additional quote before the equal sign.
- If there is a "goto enoughSpace" command, then must be the :enoughSpace label.
- The main program requires a "setlocal EnableDelayedExpansion" command, because it execute: "if !drive[%drive%]! gtr !file[%file%]! goto enoughSpace".
- On the other hand, if you insert a "setlocal EnableDelayedExpansion" command at beginning of DecimalToPowerOf1024 subroutine, when the subroutine ends all variables created there will be deleted, so the main program will not recieve the calculated values.
- You must insert a "goto :EOF" command after the "pause" command; otherwise, after press a key the program continue with the code of the subroutine with no parameter. This, of course, produce "missing operator" error.
This is the corrected code:
Code: Select all
@echo on
setlocal EnableDelayedExpansion
set file="C:\Users\xxx\Videos\movie\VIDEO_TS\all.vob"
for %%F in (%file%) do set "filesize=%%~zF"
for /F "tokens=3" %%F in ('dir /-C "%~N0.bat"') do set "availableSpace=%%F"
call :DecimalToPowerOf1024 %filesize% %file%
call :DecimalToPowerOf1024 %availableSpace% %drive%
rem Test if availableSpace in drive is greater than filesize:
rem If there are more groups of numbers in drive than in file
if %drive% gtr %file% goto enoughSpace
rem If there are the same groups of numbers and drive number is greater than file number
if %drive% equ %file% if !drive[%drive%]! gtr !file[%file%]! goto enoughSpace
echo Not enough space
pause
goto :EOF
:enoughSpace
echo Enough space: proceed to copy
pause
goto :EOF
:DecimalToPowerOf1024
rem DecimalToPowerOf1024.bat bigNumber [arrayName]
rem Decimal to power-of-1024 base conversion of an unlimited size decimal number
rem Antonio Perez Ayala
rem Get the name of the array, if any
set power=PowerOf1024
if "%~2" neq "" set "power=%~2"
rem Divide the number in 9-digits groups, eliminating left zeros in each group
set number=%1
set groups=0
:nextGroup
set group=%number:~-9%
for /L %%a in (1,1,8) do if "!group:~0,1!" equ "0" set group=!group:~1!
set /A groups+=1
set group[%groups%]=%group%
set number=%number:~0,-9%
if defined number goto nextGroup
rem Convert the 9-digits groups to power-of-1024 values
set /A bitPos=0, %power%=0, %power%[0]=0
:nextBinaryDigit
rem Divide the 9-digits groups by 2
set carry=0
for /L %%i in (%groups%,-1,1) do (
set /A term=carry*1000000000+group[%%i], group[%%i]=term/2, carry=term%%2
)
rem Insert remainder in current PowerOf1024 value, in right-to-left order
set /A "%power%[!%power%!]+=carry<<bitPos, bitPos+=1"
rem If current PowerOf1024 value completed: pass to next one
if %bitPos% equ 10 set /A bitPos=0, %power%+=1 & set %power%[!%power%!]=0
rem If last (most significant) group was completely converted: eliminate it
if !group[%groups%]! equ 0 set /A groups-=1
rem And pass to convert the rest of 9-digits groups
if %groups% gtr 0 goto nextBinaryDigit
for %%p in (!%power%!) do if !%power%[%%p]! equ 0 set "%power%[%%p]=" & set /A %power%-=1
exit /B
Antonio
Re: Help with File Size Calculations
Posted: 13 Jan 2014 21:55
by julesverne
Thanks for the suggestions all! I was about to start down that road until @Aacini helped. Thanks @Aacini
So I've been working on correcting that code that I posted all day long. I've gotten pretty good at deciphering bat files but your code was definitely a difficult nut for me to crack. I was getting close to figuring it out (including all the bugs you mentioned save 1 -
The main program requires a "setlocal EnableDelayedExpansion" command, because it execute: "if !drive[%drive%]! gtr !file[%file%]! goto enoughSpace".
). And I just changed that as well... so I think at some point I may have gotten it, I at least would've been pining over it for awhile.
Anyway, I really appreciate your help with the code. Not the first time you've helped me. I just tested it out and works perfect. Thanks again!
Re: Help with File Size Calculations
Posted: 14 Jan 2014 01:29
by foxidrive
julesverne wrote:Hi Foxidrive, thanks! Unfortunately, the reason this won't work for me is the Windows 32 bit size limit.
Did you test it? I think you will find that it doesn't have a 32 bit limit and is byte accurate.
Re: Help with File Size Calculations
Posted: 14 Jan 2014 10:20
by julesverne
@foxidrive
julesverne wrote:
Hi Foxidrive, thanks! Unfortunately, the reason this won't work for me is the Windows 32 bit size limit.
Did you test it? I think you will find that it doesn't have a 32 bit limit and is byte accurate.
I did test it, only a couple times. Admittedly I didn't try hard enough to fix the problem that I realized, I was creating for myself. It works great! and real short code. I LOVE IT!!
Despite my issues with getting all this working... All the debugging I did yesterday and just now definitely widened my knowledge of working in bat and hopefully in the future this will help me help others.
Thanks for your help @foxidrive
Re: Help with File Size Calculations
Posted: 14 Jan 2014 10:39
by Aacini
foxidrive wrote:julesverne wrote:Hi Foxidrive, thanks! Unfortunately, the reason this won't work for me is the Windows 32 bit size limit.
Did you test it? I think you will find that it doesn't have a 32 bit limit and is byte accurate.
You are right in the sense that VBS/JScript numbers are not limited to 32 bits, so this may be used in simpler solutions. For example, this one uses JScript:
Code: Select all
@echo off
set file="C:\Users\xxx\Videos\movie\VIDEO_TS\all.vob"
for %%F in (%file%) do set "filesize=%%~zF"
for /F "tokens=3" %%F in ('dir /-C "%~N0.bat"') do set "availableSpace=%%F"
>"%temp%\geq.js" echo WScript.Quit(%availableSpace%^>=%filesize%?0:1)
cscript //nologo "%temp%\geq.js"
if %errorlevel% equ 0 (
echo Enough space: proceed to copy
) else (
echo Not enough space
)
del "%temp%\geq.js"
pause
However, this does
NOT means that VBS/JScript method can correctly process big numbers like the one posted at beginning of this thread (comprised of 30 digits). I searched the web looking for the number of significant digits that VBS/JScript may process and found nothing, so I did a test. I modified your code this way:
Code: Select all
@echo off
set calc=%1-%2
echo %calc%
>"%temp%\VBS.vbs" echo if (%calc%) ^> -1 then wscript.echo "yes" else wscript.echo "no"
for /f "delims=" %%a in ('cscript /nologo "%temp%\VBS.vbs"') do set "result=%%a"
del "%temp%\VBS.vbs"
echo %result%
... called it geq.bat and tested on numbers every time larger. The result was wrong when the numbers have just 17 digits...
Code: Select all
C:\> geq 1234 1235
1234-1235
no
C:\> geq 1234 1233
1234-1233
yes
C:\> geq 1234567890123456 1234567890123459
1234567890123456-1234567890123459
no
C:\> geq 12345678901234567 12345678901234569
12345678901234567-12345678901234569
yes
Antonio