Page 1 of 2
Directory Size
Posted: Sat Oct 01, 2005 3:47 am
by trather
I am trying to make a program that will get the size of a directory.
This is what I have done but the size doesn't come back with a number
Code: Select all
F_Name.s=""
Size.l = 0
Test.s = "C:\Documents and Settings\User"
If ExamineDirectory(0, Test, "*.*")
Repeat
FileType = NextDirectoryEntry()
If FileType
F_Name = DirectoryEntryName()
Debug F_Name
If F_Name = "My Documents"
Size = DirectoryEntrySize()
EndIf
Debug Size
Size = 0
If FileType = 2 ; Directory type
EndIf
EndIf
Until FileType = 0
Else
MessageRequester("Error","Can't examine this directory: ",0)
EndIf
Re: Directory Size
Posted: Sat Oct 01, 2005 1:37 pm
by NoahPhense
This one works well, it's in the code archive on your system:
Make sure you keep that last / on there ..
Code: Select all
; English forum: http://purebasic.myforums.net/viewtopic.php?t=6585&highlight=
; Author: Freak
; Date: 16. June 2003
; But be aware that if you have many big files then the total size may be
; reported incorrectly due to limitations (missing big numbers) in PureBasic...
Procedure.l DirectorySize(ID.l, Directory.s)
Protected Size.l
If ExamineDirectory(ID, Directory, "*.*")
Repeat
Entry.l = NextDirectoryEntry()
If Entry = 1
Size + DirectoryEntrySize()
ElseIf Entry = 2
Name.s = DirectoryEntryName()
If Name <> ".." And Name <> "."
Size + DirectorySize(ID+1, Directory+Name+"\")
UseDirectory(ID)
EndIf
EndIf
Until Entry = 0
EndIf
ProcedureReturn Size
EndProcedure
; Use 0 as ID, it is only needed for the recursive calls
Debug DirectorySize(0, "C:\Documents and Settings\administrator\My Documents\")
;Debug DirectorySize(0, "C:\Windows\")
- np
Posted: Sat Oct 01, 2005 4:58 pm
by trather
I had tried that one but I was getting wrong number for the large directory. So I was trying to understand how to handle large directory over 3 gig .
Posted: Sat Oct 01, 2005 5:55 pm
by Pupil
trather wrote:I had tried that one but I was getting wrong number for the large directory. So I was trying to understand how to handle large directory over 3 gig .
That's a bit more complex as PB at the moment don't support variable types that can store larger values than 4G approx. (unless you count floats but that probably isn't a good option here). There's some user libs around that let you deal with larger numbers...
Posted: Sat Oct 01, 2005 7:24 pm
by fweil
Just one possible way to solve this : do you need an accurate precision ?
This works well enough for very large folders and volumes :
Code: Select all
; English forum: http://purebasic.myforums.net/viewtopic.php?t=6585&highlight=
; Author: Freak
; Date: 16. June 2003
; But be aware that if you have many big files then the total size may be
; reported incorrectly due to limitations (missing big numbers) in PureBasic...
Procedure.f DirectorySize(ID.l, Directory.s)
Protected Size.f
If ExamineDirectory(ID, Directory, "*.*")
Repeat
Entry.l = NextDirectoryEntry()
If Entry = 1
Size + DirectoryEntrySize()
ElseIf Entry = 2
Name.s = DirectoryEntryName()
If Name <> ".." And Name <> "."
Size + DirectorySize(ID+1, Directory+Name+"\")
UseDirectory(ID)
EndIf
EndIf
Until Entry = 0
EndIf
ProcedureReturn Size
EndProcedure
; Use 0 as ID, it is only needed for the recursive calls
Debug DirectorySize(0, "C:\Documents and Settings\administrator\My Documents\")
;Debug DirectorySize(0, "C:\Windows\")
Posted: Sun Oct 02, 2005 5:10 pm
by trather
Yes. I am trying to compair directory sizes to know if it needs to be copied. If the sizes are the same then I can skip but if I am not getting true numbers then I have a problem.
Posted: Sun Oct 02, 2005 7:44 pm
by fweil
So you could use extended integers. This would give you the exact bytes quantity.
Obviously Purebasic does not render it on the screen this is easy to save two longs somewhere for comparizon.
Posted: Sat Oct 08, 2005 4:10 am
by trather
I am not sure that I understand.
Posted: Sat Oct 08, 2005 11:21 pm
by fweil
You could use a structure to define a 64 bits variable like :
Structure Integer64
l1.l
l2.l
EndStructure
then receive the 64 bits value rendered using API functions, and compare both 32 bits longs stored somewhere with a later 64 bits value you would like to check.
Posted: Sun Oct 09, 2005 2:13 am
by NoahPhense
fweil wrote:You could use a structure to define a 64 bits variable like :
Structure Integer64
l1.l
l2.l
EndStructure
then receive the 64 bits value rendered using API functions, and compare both 32 bits longs stored somewhere with a later 64 bits value you would like to check.
Do you mean kind of like how we are handling doubles right now?
If so, can you throw together a quick example for us.. Sorry

if we don't
ask, we will never move forward mentally.
Much appreciated!
- np
Posted: Sun Oct 09, 2005 9:28 am
by fweil
Well, sorry, I was busy and then lazy up to this morning to draw a small sample code.
This is there something I meant by using large integers returned from API functions. In this sample code I use the volume extended information, returning bytes numbers larger than 2GB.
It works easy and can be processed in any program I guess (but only Windows API. I don't know about other platforms).
Note that I show float recalculted values just for understanding on how to display it, as it is not necessary to convert large integers values to floats for comparison.
Then you can look forward in using other file or filesystem commands to process file size or directory size comparizons.
Tell me if you are on the way with this.
Code: Select all
;
; ULARGE_INTEGER is part of API structures integrated in Purebasic
;
;Structure ULARGE_INTEGER
; LowPart.l
; HighPart.l
;EndStructure
DirectoryName.s = "C:\"
; returns 1 if processed well
Debug GetDiskFreeSpaceEx_(@DirectoryName, @FreeBytesAvailableToCaller.ULARGE_INTEGER, @TotalNumberOfBytes.ULARGE_INTEGER, @TotalNumberOfFreeBytes.ULARGE_INTEGER)
; returns HighPart * $100000000 + LowPart value
Debug FreeBytesAvailableToCaller\LowPart
Debug FreeBytesAvailableToCaller\HighPart
f.f = FreeBytesAvailableToCaller\HighPart * $10000 * $10000 + FreeBytesAvailableToCaller\LowPart
Debug f
; idem
Debug TotalNumberOfBytes\LowPart
Debug TotalNumberOfBytes\HighPart
f.f = TotalNumberOfBytes\HighPart * $10000 * $10000 + TotalNumberOfBytes\LowPart
Debug f
; idem
Debug TotalNumberOfFreeBytes\LowPart
Debug TotalNumberOfFreeBytes\HighPart
f.f = TotalNumberOfFreeBytes\HighPart * $10000 * $10000 + TotalNumberOfFreeBytes\LowPart
Debug f
CallDebugger
End
Posted: Sun Oct 09, 2005 4:54 pm
by trather
Thank you for the code
.
I have been trying to use this some API command but I can only get the size of the whole drive. Even if I change the directory. I have tried both "C:\windows" and "C:\windows\" and I get the same answer if I do just "C:\". I must be missing something but what I need to be able to do is see the total size of on directory and any sub directories that might be there.
What I am trying to do is look at the "My Documents" of each user on an XP Computer and compair that to the a copy of that users "My Documents" that I have copied off of the local computer and put on a Network server that they don't have access to. If I can check the size of the whole "My Documents" and it is not the same as the one that I have saved then I will just recopy it.
Posted: Sun Oct 09, 2005 6:48 pm
by Droopy
Using PBOSL I Tweaked Freak code
No size limitation
Code: Select all
;/ Return size of the Directory ( in Byte ) as a String
;/ Required PBOSB ( BigNum )
; Author: Freak Tweaked by Droopy ( Added BigNum )
; Date: 16. June 2003 / Tweaked 9/10/05
Procedure.s DirectorySizeInternal(ID.l, Directory.s)
If ExamineDirectory(ID, Directory, "*.*")
Repeat
Entry.l = NextDirectoryEntry()
If Entry = 1
Total.s=BIGNUMADD(Total.s,Str(DirectoryEntrySize()))
ElseIf Entry = 2
Name.s = DirectoryEntryName()
If Name <> ".." And Name <> "."
Temp.s=DirectorySizeInternal(ID+1, Directory+Name+"\")
Total.s=BIGNUMADD(Total.s,Temp.s)
UseDirectory(ID)
EndIf
EndIf
Until Entry = 0
EndIf
ProcedureReturn Total.s
EndProcedure
Procedure.s DirectorySize(Directory.s)
If Left(Directory,1)<>"\" : Directory +"\":EndIf
ProcedureReturn DirectorySizeInternal(0,Directory)
EndProcedure
;/ Test
#Directory="C:\Windows\"
MessageRequester(#Directory,DirectorySize(#Directory)+" Bytes")
Posted: Sun Oct 09, 2005 6:56 pm
by NoahPhense
We're trying not to use a lib.. unless we can get the source..
But for the record. I tried that code, and it doesn't like my (3) 4.6gb files.
- np
Posted: Sun Oct 09, 2005 6:58 pm
by NoahPhense
Thanks Fweil. That is what we were looking for. A way to store and play
with the large numbers.
So we'll probably have to go with API when getting dir sizes too.. because
the native pb commands, don't allow us to store large numbers.. ?
- np