2

Hello I'm trying to figure out how to have my results show in MB so its more readable instead of bytes. This script is used for monitoring a common folder in a list of servers.

Thank you for any help provided. I searched around on google for quite awhile but couldn't figure this out on my own.

ECHO     DATE: %DATE% > filecount.TXT
ECHO     TIME: %TIME% >> filecount.TXT
ECHO     USER: %USERNAME% >> filecount.TXT
ECHO COMPUTER: %COMPUTERNAME% >> filecount.TXT
ECHO. >> filecount.TXT
ECHO. >> filecount.TXT
ECHO. >> filecount.TXT
FOR /F "tokens=1" %%i in (servers.txt) DO (
 ECHO   %%i  ::: >> filecount.TXT 
 ECHO Counting %%i
 dir \\%%i\c$\folder1\folder2  | findstr "File(s)"  >> filecount.TXT 

 ECHO. >> filecount.TXT  
 ECHO. >> filecount.TXT  
)

:::::::::::::::::::::::: END SCRIPT :::::::::::::::::::::::::
Samuel Willis
  • 21
  • 1
  • 3
  • You can take a look at this answer ==> [Get size of a directory in 'MB' using batch file](http://stackoverflow.com/questions/36301198/get-size-of-a-directory-in-mb-using-batch-file) – Hackoo Mar 11 '17 at 07:13

4 Answers4

2

You can conveniently and efficiently use ROBOCOPY to get cumulative file counts and file sizes. It will automatically convert large values to kilobytes, megabytes, or gigabytes, (or possibly terabytes?).

I put the code to get the file count and file size in its own subroutine.

I also simplified the code by putting the main block of code in parentheses and redirecting only once - it is easier to write, and it is more efficient (faster).

I also added code to translate t, g, m, k, and blank into TB, GB, MB, KB, and B. The code would be simpler without the translation.

I'm pretty sure the code would have to change if your language is not English.

@echo off
setlocal

:: Initialize unit translation
for /f "eol== delims==" %%V in ('set unit_ 2^>nul') do set "%%V="
for %%A in ("t=TB" "g=GB" "m=MB" "k=KB") do set "unit_%%~A"

> filecount.TXT (
  echo     DATE: %DATE%
  echo     TIME: %TIME%
  echo     USER: %USERNAME%
  echo COMPUTER: %COMPUTERNAME%
  echo(
  echo(
  echo(
  for /f "tokens=1" %%S in (servers.txt) do (
    echo   %%S  :::
    echo Counting %%S
    call :printSize "\\%%S\c$\folder1\folder2"
    echo(
    echo(
  )
)
exit /b

:printSize %1
setlocal
for /f "tokens=1,3,4" %%A in (
  'robocopy %1 %1 /l /is /nfl /ndl /njh'
) do (
  setlocal enableDelayedExpansion
  if %%A == Files (
      set "files=                %%B"
  ) else if %%A == Bytes (
    set "bytes=        %%B"
    set "unit=!unit_%%C!"
    if not defined unit set "unit=B"
  )
)
echo %files:~-16% File(s)  %bytes:~-8% %unit%
exit /b
dbenham
  • 127,446
  • 28
  • 251
  • 390
  • 1
    @MagicallyDelicous - Functionally it does not matter. But when redirecting a parenthesized block I prefer to redirect before the block instead of after because I find it easier to understand - The reader knows right away that the block is redirected, instead of waiting to find out at the end of the block. – dbenham Mar 11 '17 at 18:53
  • 1
    @MagicallyDelicous - Once a block begins, any `)` that does not close a `(` must be either escaped as `^)`, or else quoted like `"anything ) anything"`. You can get around that problem in this case by putting the code in a subroutine instead of a parenthesized block, and then redirect the `CALL :yourRoutine >output.txt` – dbenham Mar 11 '17 at 22:19
  • This not work for my italian version. The output of robocopy is language dependent :( – Einstein1969 Mar 27 '17 at 18:57
  • 1
    @Einstein1969 - That is why the last sentence stated *"I'm pretty sure the code would have to change if your language is not English."*. I should think you could adapt the code for other languages. But I agree, the language dependency is far from ideal. – dbenham Mar 27 '17 at 20:26
1

Here's a batch function that'll convert an integer into a human readable B / KB / MB / GB convention. It uses a bit mask one bit to the right of the most significant bit to check whether the final value should be rounded up. Put this at the bottom of your script below the final exit /b or goto :EOF:

:humansize <return_var> <int>
setlocal enabledelayedexpansion
set "unit=B"
set /a "mask = 512, roundup = 0, size = %~2"
for %%I in (KB MB GB) do (
    if !size! geq 1024 (
        set "unit=%%I"
        set /a "roundup = size & mask, size >>= 10"
    )
)
if %roundup% gtr 0 set /a "size += 1"
endlocal & set "%~1=%size% %unit%" & exit /b

Example usage:

call :humansize human 1536
rem // %human% now contains "2 KB"

call :humansize human 1535
rem // %human% now contains "1 KB"

Be advised that batch math is limited to 32-bit signed integers (2GB).

rojo
  • 24,000
  • 5
  • 55
  • 101
0

The SET command cannot do floating point math, so this is technically an estimation. Also you are limited to 32 bit Integers. So the largest byte size you can do math on is 2147483647

@echo off
ECHO     DATE: %DATE% > filecount.TXT
ECHO     TIME: %TIME% >> filecount.TXT
ECHO     USER: %USERNAME% >> filecount.TXT
ECHO COMPUTER: %COMPUTERNAME% >> filecount.TXT
ECHO. >> filecount.TXT
ECHO. >> filecount.TXT
ECHO. >> filecount.TXT
FOR /F "tokens=1" %%i in (servers.txt) DO (
    ECHO   %%i  ::: >> filecount.TXT 
    ECHO Counting %%i
    FOR /F "tokens=1-4 delims= " %%G IN ('dir /-C \\%%i\c$\folder1\folder2 ^| findstr "File(s)"') DO (
        set size=%%I
        set bytes=%%J
        setlocal enabledelayedexpansion
        IF !size! GEQ 1048576 (
            set /a size/=1048576
            set bytes=MB
        )
        echo %%G %%H     !SIZE! !bytes! >> filecount.TXT  
        endlocal
    )
    ECHO. >> filecount.TXT  
    ECHO. >> filecount.TXT  
)
pause
:::::::::::::::::::::::: END SCRIPT :::::::::::::::::::::::::
Squashman
  • 13,649
  • 5
  • 27
  • 36
0

Batch Script Get Total Sum by Size and Count of Files within a Folder

Attached is a batch script method that will get you the KB, MB, and GB along with all the other detail you needed from your script. It'll all go to the log file and be appended accordingly while still iterating through the file list of servers getting the sum and counts of the files within the directory.


Batch Script

Set the LogFile and ServerList variables up top. Set the directory to get the file detail from within the FOR loop still as an argument passed with the call command passing that as an argument tp the dynamic PowerShell script build routine that does the calculations, etc.

@ECHO ON

SET LogFile=filecount.TXT
SET ServerList=Servers.txt

ECHO.........................................>> "%LogFile%"
ECHO DATE: %DATE%             >> "%LogFile%"
ECHO TIME: %TIME%             >> "%LogFile%"
ECHO USER: %USERNAME%         >> "%LogFile%"
ECHO COMPUTER: %COMPUTERNAME% >> "%LogFile%"
ECHO.                         >> "%LogFile%"

FOR /F "TOKENS=1" %%i IN (%ServerList%) DO (
    ECHO ~~~Counting %%~i~~~             >> "%LogFile%"
    CALL :PowerShellBuild "\\%%~i\c$\folder1\folder2"
)
ECHO.........................................>> "%LogFile%" 
EXIT
GOTO EOF
:::::::::::::::::::::::: END OF SCRIPT STILL :::::::::::::::::::::::::

:PowerShellBuild
SET TmpPSScript=%Temp%\~tmpFileCalc.ps1
IF EXIST "%TmpPSScript%" DEL /Q /F "%TmpPSScript%"

ECHO $Folder  = "%~1"                >>"%TmpPSScript%"
ECHO $Files   = Get-ChildItem $folder>>"%TmpPSScript%"
ECHO $KBTotal = ($files ^| Measure-Object -Sum Length).Sum / 1kb >>"%TmpPSScript%"
ECHO $MBTotal = ($files ^| Measure-Object -Sum Length).Sum / 1mb >>"%TmpPSScript%"
ECHO $GBTotal = ($files ^| Measure-Object -Sum Length).Sum / 1gb >>"%TmpPSScript%"
ECHO $Count   = ($files ^| Measure-Object).count                 >>"%TmpPSScript%"

ECHO $KBTotal = [math]::Round($KBTotal, 2) >>"%TmpPSScript%"
ECHO $MBTotal = [math]::Round($MBTotal, 2) >>"%TmpPSScript%"
ECHO $GBTotal = [math]::Round($GBTotal, 2) >>"%TmpPSScript%"

ECHO ECHO "Count: $Count" ^| Out-File -encoding ascii -append "%LogFile%" >>"%TmpPSScript%"
ECHO ECHO "KB: $KBTotal" ^| Out-File -encoding ascii -append "%LogFile%"  >>"%TmpPSScript%"
ECHO ECHO "MB: $MBTotal" ^| Out-File -encoding ascii -append "%LogFile%"  >>"%TmpPSScript%"
ECHO ECHO "GB: $GBTotal" ^| Out-File -encoding ascii -append "%LogFile%"  >>"%TmpPSScript%"

:PowerShellExec
SET PowerShellDir=C:\Windows\System32\WindowsPowerShell\v1.0
CD /D "%PowerShellDir%"
Powershell -ExecutionPolicy Bypass -Command "& '%TmpPSScript%'"
GOTO EOF

My Test Example Script

enter image description here

Result

........................................
DATE: Sat 03/11/2017             
TIME: 16:52:32.48             
USER: User         
COMPUTER: FBIPC

~~~Counting Clutter~~~             
Count: 15
KB: 2490.48
MB: 2.43
GB: 0
~~~Counting Photowork~~~             
Count: 7
KB: 372.88
MB: 0.36
GB: 0
........................................ 

Native PowerShell

Test the syntax on your system(s) with the native PowerShell to confirm it works at this level from the PowerShell ISE app but it works for my with Windows 10 with PowerShell 5.0 and Windows 7 with PowerShell 4.0

$LogFile  = "C:\Users\User\Desktop\Scripts\logfile.log"
$Folder  = "C:\Users\User\Desktop\Scripts"

$Files   = Get-ChildItem $folder
$KBTotal = ($files | Measure-Object -Sum Length).Sum / 1kb
$MBTotal = ($files | Measure-Object -Sum Length).Sum / 1mb
$GBTotal = ($files | Measure-Object -Sum Length).Sum / 1gb
$Count   = ($files | Measure-Object).count

$KBTotal = [math]::Round($KBTotal, 2)
$MBTotal = [math]::Round($MBTotal, 2)
$GBTotal = [math]::Round($GBTotal, 2)

ECHO "Count: $Count" | Out-File -encoding ascii -append $Logfile
ECHO "KB: $KBTotal" | Out-File -encoding ascii -append $Logfile
ECHO "MB: $MBTotal" | Out-File -encoding ascii -append $Logfile
ECHO "GB: $GBTotal" | Out-File -encoding ascii -append $Logfile

Further Resources

Bitcoin Murderous Maniac
  • 1,209
  • 1
  • 14
  • 27
  • It appears to be going to the servers.txt file but its not logging anything. Can we talk further about this? – Samuel Willis Mar 11 '17 at 16:27
  • @SamuelWillis Let me know how it goes when you get a chance and if you still have trouble with this... – Bitcoin Murderous Maniac Mar 14 '17 at 00:10
  • Thanks for the follow up @MagicallyDelicous I ended up using dbenham code as it ran faster and I preferred the logging results. I tested your code and it works too. Again thank you both for helping. – Samuel Willis Mar 15 '17 at 01:04