For Loop to Retrieve Average File Sizes

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
davep
Posts: 24
Joined: 29 May 2008 14:03
Location: Nauf Kakalak

For Loop to Retrieve Average File Sizes

#1 Post by davep » 28 Apr 2009 20:01

Hello all,

I'm trying to get the average file size of three file types within a folder. The script below partially works, but only on the last of the three file types, and therefore only echoes one set of results. If I move the final closing parenthesis to the end of the script (from line 17 to line 32), I get all three file types displayed, but no actual numerical results. I think I need another loop, or a function of some sort, but I'm quite stuck. Any advice is appreciated.

Code: Select all

@echo off

SETLOCAL

title Average File Sizes

set LOC=c:\logs
set MATH="C:\Program Files\math\math.exe"
set DIV=---------------------------------

for %%A in (.log,.txt,.stats) do (
   echo.%DIV%
   for /f "usebackq tokens=1,3 delims= " %%X in (`dir %LOC%\*%%A ^| findstr "File(s)"`) do (
      set num=%%X
      set size=%%Y
      )
   )
   set "size=%size:,=%"
   echo.Found %num% *%%A files
   echo.
     for /f "usebackq" %%M in (`%MATH% %size%/%num%`) do set avgB=%%M
      for /f "usebackq" %%N in (`%MATH% %size%/%num%/1024`) do set avgKB=%%N
      for /f "usebackq" %%O in (`%MATH% %size%/%num%/1024/1024`) do set avgMB=%%O
      for /f "usebackq" %%P in (`%MATH% %size%/%num%/1024/1024/1024`) do set avgGB=%%P
         echo.Average Size is:
      echo.
   echo. B %avgB%
      echo.KB %avgKB%
      echo.MB %avgMB%
      echo.GB %avgGB%
      echo.
   
pause



Also, line 19 (echo.Found %num% *%%A files) does not return the value for %%A. I know that's a clue, but I lack the know-how to continue.

The way it is now, I get these results:

Code: Select all

---------------------------------
---------------------------------
---------------------------------
Found 2 *%A files

Average Size is:

 B 41216107
KB 40250.1045
MB 39.3067427
GB 0.0383854909

Press any key to continue . . .


And if I move the closing parenthesis to line 32, I get this:

Code: Select all

---------------------------------
Found  *.log files

Average Size is:

 B
KB
MB
GB

---------------------------------
Found  *.txt files

Average Size is:

 B
KB
MB
GB

---------------------------------
Found  *.stats files

Average Size is:

 B
KB
MB
GB

Press any key to continue . . .


That's the layout I want, but as you see there's no data.

Thank you, and I'm looking forward to advice from the masters...

RElliott63
Expert
Posts: 80
Joined: 04 Feb 2009 10:03

#2 Post by RElliott63 » 29 Apr 2009 08:38

Here's a start for you. . You might want to change out for doing your math by the "Math.exe" method, but it works:

Code: Select all

@echo off

SETLOCAL ENABLEEXTENSIONS
SETLOCAL ENABLEDELAYEDEXPANSION

Set Total=0
Set Count=0

Cls
Echo Calculating file sizes...
Echo;

For /D %%A in (.Log,.Bat,.Stats) Do (
    Echo Looking for %%A files...
    If Exist *%%A (
     Echo -- Found %%A files!
       For /F "Delims=" %%F In ('Dir /B *%%A') Do (
           Call :GetFileInfo "%%F"
           Set /A Count=Count+1
           Set /A Total=Total+file.size
       )
    )  Else (
       Echo -- No %%A files found!
    )
    Echo;
)

Echo Number of Files:  %Count%
Echo Total Size:       %Total%

Set /A AvgB=Total/Count
Set /A AvgKB=AvgB/1024
Set /A AvgMB=AvgKB/1024
Set /A AvgGB=AvgMB/1024

Echo -------------------------------------
Echo;
Echo Average Size is:  %AvgB%
Echo;
Echo  B   %Total%
Echo KB   %AvgKB%
Echo MB   %AvgMB%
Echo GB   %AvgGB%
Echo;
Echo -------------------------------------

Goto:EOF



:: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
:: Get current File Information
:: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
:GetFileInfo

 Set "Fn=%1"

 For /F %%F in ('Dir /B %FN%') Do (

     Set  file.NAME="%%~nxF"
     Set "file.PATH=%%~pF"
     Set "file.SIZE=%%~zF"

     Set "d=%%~tF"
     Set "dD=!d:/=!"
     Set "dT=!d::=!"
     Set "dH=!dT:~11,2!"  -- Hours
     Set "dM=!dT:~13,2!"  -- Minutes
     Set "ap=!dT:~16,2!"  -- AM / PM

     If /I [!ap!] EQU [PM] (
        Set /A dH=dH+12
     )

     Set "file.DATE=!dD:~0,8%!
     Set "file.TIME=!dH!!dM!"

)
Goto:EOF


avery_larry
Expert
Posts: 391
Joined: 19 Mar 2009 08:47
Location: Iowa

#3 Post by avery_larry » 29 Apr 2009 11:02

I would like to mention that using the set /a math, you will be limited to about 2Gb in total sum file size before it chokes. Probably won't happen with log, bat, or stats files but worth mentioning . ..

davep
Posts: 24
Joined: 29 May 2008 14:03
Location: Nauf Kakalak

#4 Post by davep » 29 Apr 2009 13:55

@RElliot63: Thanks for the nudge in the right direction. I forsee a tweak or two to get your code to merged with mine. For example, how would I keep the set LOC line I originally had? I need that, or something similar, so I can send the script to a coworker and let him choose the server and path, and execute from a different machine altogether.

@avery_larry: You're right, that's why I use math.exe whenever I can. It handles decimals, too.

@both: I'll report back as soon as I can; with either more questions or a solution. Thanks!

avery_larry
Expert
Posts: 391
Joined: 19 Mar 2009 08:47
Location: Iowa

#5 Post by avery_larry » 29 Apr 2009 14:10

I think all you need is delayedexpansion since everything you're doing is in a for loop:

Code: Select all

@echo off 

SETLOCAL enabledelayedexpansion

title Average File Sizes

set LOC=c:\logs
set MATH="C:\Program Files\math\math.exe"
set DIV=---------------------------------

for %%A in (.log,.txt,.stats) do (
   echo.%DIV%
   for /f "usebackq tokens=1,3 delims= " %%X in (`dir /-c %LOC%\*%%A ^| findstr "File(s)"`) do (
      set num=%%X
      set size=%%Y
   )
   echo.Found !num! *%%A files
   echo.
     for /f "usebackq" %%M in (`%MATH% !size!/!num!`) do set avgB=%%M
      for /f "usebackq" %%N in (`%MATH% !size!/!num!/1024`) do set avgKB=%%N
      for /f "usebackq" %%O in (`%MATH% !size!/!num!/1024/1024`) do set avgMB=%%O
      for /f "usebackq" %%P in (`%MATH% !size!/!num!/1024/1024/1024`) do set avgGB=%%P
         echo.Average Size is:
      echo.
   echo. B !avgB!
      echo.KB !avgKB!
      echo.MB !avgMB!
      echo.GB !avgGB!
      echo.
)   
pause


also -- dir /-c gets rid of commas for you.

davep
Posts: 24
Joined: 29 May 2008 14:03
Location: Nauf Kakalak

Bingo!

#6 Post by davep » 29 Apr 2009 14:21

Perfect, sir! You've done it again!

Here's the results:
---------------------------------
Found 2 *.log files

Average Size is:

B 18932546.5
KB 18488.8149
MB 18.0554833
GB 0.017632308

---------------------------------
Found 2 *.txt files

Average Size is:

B 28359080.5
KB 27694.4146
MB 27.0453267
GB 0.0264114519

---------------------------------
Found 2 *.stats files

Average Size is:

B 41216107
KB 40250.1045
MB 39.3067427
GB 0.0383854909

Press any key to continue . . .


Thank you very much!

davep
Posts: 24
Joined: 29 May 2008 14:03
Location: Nauf Kakalak

#7 Post by davep » 29 Apr 2009 14:59

Upon further testing, I've found a loophole. If file not found, the last known "good" data will be displayed twice.
---------------------------------
Found 1 *.txt files

Average Size is:

B 468998524
KB 458006.371
MB 447.271847
GB 0.436788913

---------------------------------
File Not Found
Found 1 *.stats files

Average Size is:

B 468998524
KB 458006.371
MB 447.271847
GB 0.436788913

---------------------------------


Any ideas?

RElliott63
Expert
Posts: 80
Joined: 04 Feb 2009 10:03

#8 Post by RElliott63 » 30 Apr 2009 08:10

Yes... back in the code I put up top, look for the:

Code: Select all

    If Exist *%%A ( 
     Echo -- Found %%A files!
       For /F "Delims=" %%F In ('Dir /B *%%A') Do (
           Call :GetFileInfo "%%F"
           Set /A Count=Count+1
           Set /A Total=Total+file.size
       )
    )  Else (
       Echo -- No %%A files found!
    )


Just include the "If Exist ..." line around your For loop. That way it doesn't get into the loop unless it finds files that are associated to the process.

-R

RElliott63
Expert
Posts: 80
Joined: 04 Feb 2009 10:03

#9 Post by RElliott63 » 30 Apr 2009 08:11

Yes... back in the code I put up top, look for the:

Code: Select all

    If Exist *%%A ( 
     Echo -- Found %%A files!
       For /F "Delims=" %%F In ('Dir /B *%%A') Do (
           Call :GetFileInfo "%%F"
           Set /A Count=Count+1
           Set /A Total=Total+file.size
       )
    )  Else (
       Echo -- No %%A files found!
    )


Just include the "If Exist ..." line around your For loop. That way it doesn't get into the loop unless it finds files that are associated to the process.

-R

davep
Posts: 24
Joined: 29 May 2008 14:03
Location: Nauf Kakalak

#10 Post by davep » 30 Apr 2009 12:07

Done. Works nicely. Thanks everyone!

Post Reply