Page 1 of 2
Folder Size Return 0
Posted: 15 Dec 2015 09:23
by btpoole
Hello all
I am attempting to loop thru a main directory check the the subfolders for a file called log.txt. The log file contains the folder size. If the log file does not exist I want to write the directory's side to the log file and save it. The sub directories being checked are fairly small to start with, maybe 550 bytes, but when I check the size with script it returns 0. Here is part of the script. If I check the folder properties it displays approx 550. The next step would be to retrieve the value in the log file if it exist and compare it to the current size of the folder to see if it is changing.
Code: Select all
setLocal EnableDelayedExpansion
FOR /R c:\main %%G in (.) DO (
Pushd %%G
Echo now in %%G
IF EXIST log.txt. (
ECHO FILE HERE
) ELSE (
ECHO FILE IS MISSING
ECHO CREATE LOG FILE
echo DIR %%G SIZE IS: %%~zG
echo %%G~zG>log.txt
)
Popd )
Echo "back home"
)
Re: Folder Size Return 0
Posted: 15 Dec 2015 09:38
by Squashman
Did you notice you are using the command modifier correctly in the first line but not the second line.
Code: Select all
echo DIR %%G SIZE IS: %%~zG
echo %%G~zG>log.txt
Regardless of that, you would need to parse all the files in the directory and add up their size to get the total for the directory. The z modifier will not work with directories.
Re: Folder Size Return 0
Posted: 15 Dec 2015 10:02
by btpoole
Ah, thank you for pointing that out. Didn't see it. So, windows has no command to use in batch file to get directory size?
Thanks again
Re: Folder Size Return 0
Posted: 15 Dec 2015 10:51
by Squashman
Well you would only have to add two lines of code to do it.
One line to initialize a variable to ZERO.
And a FOR command to iterate over all the files in the directory.
Code: Select all
FOR %%G IN (*) DO set /a dirsize+=%%~zG
Re: Folder Size Return 0
Posted: 15 Dec 2015 10:57
by Compo
I would probably go for something like this:
Code: Select all
@Echo Off
SetLocal
(Set ID=%~1)
(Set SW=/L /S /NJH /BYTES /FP /NC /NDL /NFL /TS /XJ /R:0 /W:0)
If Not Defined ID (Set ID=%~dp0)
For /F "Tokens=1-2 Delims=: " %%a In ('RoboCopy %ID% NULL %SW%') Do (
If %%a==Bytes Echo=Directory %ID% Size in %%a=%%b)
Ping -n 11 0.0.0.0 1>Nul
Just drag and drop my directory onto it or run the script with the directory path as the parameter.
Re: Folder Size Return 0
Posted: 15 Dec 2015 18:55
by btpoole
Thank you both for valuable information.
Re: Folder Size Return 0
Posted: 16 Dec 2015 00:21
by thefeduke
This came out of generalizing your original framework and incorporating previous suggestions:
FolderSize.bat
Code: Select all
@Echo Off
:FolderSize [folder]
setLocal EnableDelayedExpansion
set "log=log.txt"
set "target=c:\main"
If .%~1 NEQ . Set "target=%~1"
set "dirsize=0"
set "dirtotal=0"
FOR /R %target% %%G in (.) DO (
Pushd %%G
FOR %%D IN (*) DO set /a dirsize+=%%~zD
echo DIR %%G SIZE IS: !dirsize!
If Exist %log% (
Echo.Found '%%~dpG%log%'
) Else (
>%log% Echo.!dirsize!
Echo.Created '%%~dpG%log%'
)
set /a dirsize=!dirsize!/1024
set /a dirtotal+=!dirsize!
set "dirsize=0"
Popd
)
Echo.Total subfolder space= '%dirtotal%' KB
Exit /b
Some output:
Code: Select all
L:\Programs>foldersize dostips
DIR L:\Programs\dostips\. SIZE IS: 213145
Created 'L:\Programs\log.txt'
DIR L:\Programs\dostips\TestNums\. SIZE IS: 59444
Created 'L:\Programs\DOStips\log.txt'
Total subfolder space= '266' KB
L:\Programs>foldersize dostips
DIR L:\Programs\dostips\. SIZE IS: 213153
Found 'L:\Programs\log.txt'
DIR L:\Programs\dostips\TestNums\. SIZE IS: 59458
Found 'L:\Programs\DOStips\log.txt'
Total subfolder space= '266' KB
L:\Programs>type dostips\log.txt
213145
I hope that it suits.
John A.
Re: Folder Size Return 0
Posted: 16 Dec 2015 01:22
by foxidrive
Those counting directory size using CMD math need to be aware that it tops out at 2 GB.
Using the DIR command in a for /f loop is another way to get the directory size, and doesn't rely on maths.
Compo wrote:I would probably go for something like this:
I had some problems with robocopy in Windows 8.1 so tweaked your code. The %~dp0 can contain & characters also so it needs to be quoted.
Using robocopy is a good plan though.
Code: Select all
@echo Off
SetLocal
Set SW=/L /S /NJH /BYTES /FP /NC /NDL /NFL /TS /XJ /R:0 /W:0
If "%~1"=="" (Set "ID=%~dp0.") else (Set "ID=%~1")
For /F "Tokens=1,3" %%a In ('RoboCopy "%ID%" "%temp%" %SW%') Do (
If "%%a"=="Bytes" Echo(The directory "%ID%" contains %%b bytes)
Ping -n 11 0.0.0.0 1>Nul
Re: Folder Size Return 0
Posted: 16 Dec 2015 16:07
by thefeduke
foxidrive wrote:Those counting directory size using CMD math need to be aware that it tops out at 2 GB.
Using the DIR command in a for /f loop is another way to get the directory size, and doesn't rely on maths.
True enough and much neater, too. That overall total was out of scope anyway.
Replace:
Code: Select all
FOR %%D IN (*) DO set /a dirsize+=%%~zD
echo DIR %%G SIZE IS: !dirsize!
with:
Code: Select all
FOR /F "usebackq tokens=1-4,5* " %%i in (`DIR /-C`) do (
IF "File(s)"=="%%j" (
set "dirsize=%%k"
Echo Folder %%G Size is: !dirsize! %%l from directory list
)
)
in my example above.
John A.
Re: Folder Size Return 0
Posted: 17 Dec 2015 09:08
by btpoole
thefeduke wrote:This came out of generalizing your original framework and incorporating previous suggestions:
FolderSize.bat
Code: Select all
@Echo Off
:FolderSize [folder]
setLocal EnableDelayedExpansion
set "log=log.txt"
set "target=c:\main"
If .%~1 NEQ . Set "target=%~1"
set "dirsize=0"
set "dirtotal=0"
FOR /R %target% %%G in (.) DO (
Pushd %%G
FOR %%D IN (*) DO set /a dirsize+=%%~zD
echo DIR %%G SIZE IS: !dirsize!
If Exist %log% (
Echo.Found '%%~dpG%log%'
) Else (
>%log% Echo.!dirsize!
Echo.Created '%%~dpG%log%'
)
set /a dirsize=!dirsize!/1024
set /a dirtotal+=!dirsize!
set "dirsize=0"
Popd
)
Echo.Total subfolder space= '%dirtotal%' KB
Exit /b
Some output:
Code: Select all
L:\Programs>foldersize dostips
DIR L:\Programs\dostips\. SIZE IS: 213145
Created 'L:\Programs\log.txt'
DIR L:\Programs\dostips\TestNums\. SIZE IS: 59444
Created 'L:\Programs\DOStips\log.txt'
Total subfolder space= '266' KB
L:\Programs>foldersize dostips
DIR L:\Programs\dostips\. SIZE IS: 213153
Found 'L:\Programs\log.txt'
DIR L:\Programs\dostips\TestNums\. SIZE IS: 59458
Found 'L:\Programs\DOStips\log.txt'
Total subfolder space= '266' KB
L:\Programs>type dostips\log.txt
213145
I hope that it suits.
John A.
Working with above I get almost exactly what I need. The one problem is that each log file after the first contains the previous subfolder sizes also. The first subfolder log.txt is correct, but each one after includes all the previous sizes. Thank you for your direction.
Re: Folder Size Return 0
Posted: 17 Dec 2015 14:57
by thefeduke
btpoole wrote:Working with above I get almost exactly what I need. The one problem is that each log file after the first contains the previous subfolder sizes also. The first subfolder log.txt is correct, but each one after includes all the previous sizes. Thank you for your direction.
I was anguishing about that while working on the accuracy of the size in the log file.
I cannot explain it. It shows correctly when I echo to the console but not when redirected to the file. I can only attribute this to the 'in (.)' of your original FOR statement. You might notice that your folder when displayed by %%G shows a '.' after it using this approach to define the loop.
Anyway, this should fix it up:
Code: Select all
@Echo Off
:FolderSize folder
setLocal EnableDelayedExpansion
set "log=log.txt"
set "target=L:\programs"
If .%~1 NEQ . Set "target=%~1"
call set "dirsize=0"
FOR /F "usebackq tokens=1-4,5* " %%E in (`DIR %target% /A:D /S /-C`) do (
IF /I "Directory" EQU "%%E" (
Pushd %%G
FOR /F "usebackq tokens=1-4,5* " %%i in (`DIR /A:-S /-C`) do (
IF "File(s)"=="%%j" (
Set "dirsize=%%k"
Echo.&Echo Folder '%%G' Size: !dirsize! %%l
)
)
If Exist %log% (
Echo.Found '%log%'
type %log%
) Else (
>%log% Echo.!dirsize!
Echo.Created '%%~dpG%log%'
)
Set "dirsize=0"
Popd
)
)
Exit /b
Run it once to build missing log files. A second run lets you see the contents to check.
I do not know how accurate you need to have the log files. By definition, when the log file is created it is in error, being short by the length of the log file just created. I did write the code to correct the contents of the log file before writing it and can move it into the above example if you go with this approach and need dead accuracy.
John A.
Re: Folder Size Return 0
Posted: 17 Dec 2015 15:31
by btpoole
Yes, I did noticed the . in the log file. I don't have to have dead accuracy. The real purpose of the log file checking the folder size is to compare it to a future run of the file to see if a process is still running and creating content. As long as the current log file content is less than the future folder size when script is ran, I know the process is still running. I couldn't think of another way to check this. I will have multiple instances of the same process running creating content in individual folders. If one of the instances stops, I hope the script checking the folder sizes initiates another script that produces a warning window, or something of the like.
Thanks for taking time in helping.
Re: Folder Size Return 0
Posted: 18 Dec 2015 01:56
by thefeduke
I corrected one line in previous post to add '%target%':
Code: Select all
FOR /F "usebackq tokens=1-4,5* " %%E in (`DIR %target% /A:D /S /-C`) do (
As it was it worked on current directory and its sub-directories.
John A.
Re: Folder Size Return 0
Posted: 23 Dec 2015 22:24
by btpoole
Once again thanks for your help but I have run into a situation. The script you provided works great for what I was trying to accomplish but something has changed. The folder structure has been changed on me.
Original structure:
C:\main\sub1
New structure:
C:\main\sub1\sub2
Yes, your script does what it was designed to do, it cycles thru the main, sub1 and sub2 getting the folder sizes. My problem is this. After my original bat file runs, the sub1 folders are created along with a log.txt file in side sub1 that stores the size of the sub1. I was then using your script in a second bat file I'll call monitor.bat which loops thru sub1 check for log.txt existence and it's content. If the value in log.txt is less than the current value of sub1, the bat will start a php script which is stored in sub1. If the value is = or > than the value of sub1 it skips and continues. Since I know have a sub2 to deal with I encounter the problem that it tries to read a log.txt in sub2 which may or may not have any content. And if the log.txt in sub2 is less than the value of sub2 it tries to start the php script in sub2 which doesn't exist. I guess what I am asking is there a way to calc the values as it is doing but only for sub1 (which would include the size of sub2) but without entering into sub2 and adding it's size up? Or a way to prevent it from trying to execute the php in sub2?
Just for refresher here is the code
Code: Select all
FOR /R %target% %%G in (.) DO (
Pushd %%G
FOR %%D IN (*) DO set /a dirsize+=%%~zD
echo DIR %%G SIZE IS: !dirsize!
If Exist %log% (
Echo.Found '%%~dpG%log%'
SET /p logsize=<log.txt
Echo CURRENT LOG SIZE . . . . . . . !logsize!
set "dirsize=0"
FOR %%D IN (*) DO set /a dirsize+=%%~zD LIMIT HERE TO sub1
Echo.NEW DIR %%G SIZE IS: !dirsize!
If !logsize! LSS !dirsize! (
Echo ********RESETTING %%G************************
start "Y:\Program Files (x86)\PHP5\php.exe" test.php
) Else (
>%log% Echo.!dirsize!
Echo NEW LOG SAVED. . . . .
)
) Else (
>%log% Echo.!dirsize!
Echo.Created '%%~dpG%log%'
)
Re: Folder Size Return 0
Posted: 24 Dec 2015 00:26
by thefeduke
btpoole wrote: is there a way to calc the values as it is doing but only for sub1 (which would include the size of sub2) but without entering into sub2 and adding it's size up? Or a way to prevent it from trying to execute the php in sub2?
As it stands now I believe that each directory could have a log file the is associated with the size of that particular directory regardless of the sizes above or below in the tree. Sub1 does not include the size of sub2 and the log file in the main target does not change while sub1 might be growing.
To develop a rule for this requirement is it safe to say that you wish to restrict log file activity to the target folder and no more that one level of sub-directory? This would imply that if you did want to act on sub2 in this structure your target would have to be C:\main\sub1\sub2 or C:\main\sub1 and that at target of C:\main would ignore sub2.
Please confirm or restate your requirement.
John A.