BunzyBuddy
(Fresh Scripter)
2006-02-22 01:51 PM
Folders sorted by size

I want to scan the size of the users HomeDirs in our HomeDirs folder, sort all folders by size and write the 3 biggest folders' name size in a textfile.

Example:
Scan all subfolders of: \\Myserver\HomeDirs$
Sort them by size, biggest on top
Write name and size of the 3 biggest folders to HomeSize.txt

I've been trying some things with GetFolderSize but I'm having some trouble to make it all work. Any help with an axample script would be realy appreciated !


Bryce
(KiX Supporter)
2006-02-22 11:06 PM
Re: Folders sorted by size

here is something...
using the UDF's
DirPlus
QuickSort


Code:

break on
call 'quicksort.udf'
call 'dirplus.udf'

$root = dirplus('c:\','/ad')

dim $folders[ubound($root)]

for $i = 0 to ubound($root)
$n = $root[$i].name
$s = val($root[$i].size)
$folders[$i] = $n,$s
next

$folders = quicksort($folders,1)

for each $item in $folders
? $item[0] " " $item[1]
next



BunzyBuddy
(Fresh Scripter)
2006-02-23 04:48 PM
Re: Folders sorted by size

Thanx for the reply.
I'm not familiair with UDF's so I'm not realy understanding how this works. Where do I put in the path to the HomeDirs and how do I write these results to a textfile ?


Bryce
(KiX Supporter)
2006-02-23 05:33 PM
Re: Folders sorted by size

in the FAQ forum, there is a sticky post "FAQ Contents Page" and in there you will find "How to use UDFs"

That should get ya started


Bryce
(KiX Supporter)
2006-02-23 05:36 PM
Re: Folders sorted by size

the path to the home dirs's would eb changed in tis line here

Code:

$root = dirplus('c:\','/ad')



that bit of code is pointing at the "c:\" and you would change your path there.

To write to a text file, look into the open() and writeline() commands.


BunzyBuddy
(Fresh Scripter)
2006-02-24 11:52 AM
Re: Folders sorted by size

Thanx Bryce
I'll give it a try
... and I'll read the "How to use UDF's" on the forum ...


BunzyBuddy
(Fresh Scripter)
2006-02-24 12:00 PM
Re: Folders sorted by size

Sorry Bryce,
I got an error on the script:

ERROR : expected expression!
Script: E:\Script test\HomeSize.kix
Line : 5


Richard H.Administrator
(KiX Supporter)
2006-02-24 12:09 PM
Re: Folders sorted by size

Have you included the UDF in your script?

BunzyBuddy
(Fresh Scripter)
2006-02-24 12:12 PM
Re: Folders sorted by size

I copied the script you wrote to a HomeSize.kix file, changed the path to the homedirs share (\\server\homedirs$) and tried to run it.

Am I forgetting something ?


Richard H.Administrator
(KiX Supporter)
2006-02-24 12:24 PM
Re: Folders sorted by size

Not my script.

Did you read the FAQ on using UDFs?

UDFs are functions written by us (or you ) - you need to include them in your script either directly or by using CALL to load them.

The simplest way is to use the links in Bryce's post above to open the UDF page, then cut-and-paste the code into your own script.


BunzyBuddy
(Fresh Scripter)
2006-02-24 03:19 PM
Re: Folders sorted by size

I'm realy sorry, I'm so stupid !
Of course, I've to put in the UDF to make it all work....

Stupid stupid stupid !!!!


NTDOCAdministrator
(KiX Master)
2006-02-24 07:13 PM
Re: Folders sorted by size

Quote:

cut-and-paste the code into your own script.




Now now Richard there will be no cutting around here, copy maybe but no cutting. That's an old bad saying that somehow stuck in eveyone's brain.


Les
(KiX Master)
2006-02-24 07:45 PM
Re: Folders sorted by size

I've been complaining for years that cut'n'paste doesn't work for me in most of the forums.

BunzyBuddy
(Fresh Scripter)
2006-02-27 09:22 AM
Re: Folders sorted by size

I inserted both UDF's in my script. Now, when I'm running it, I got an error on the QuickSort UDF in line

$LowerItem = QuickSortItem( $A[$LowerIndex],$indexcol )

ERROR: Expected expression !



NTDOCAdministrator
(KiX Master)
2006-02-27 09:34 AM
Re: Folders sorted by size

Well not sure what you're doing as there is no UDF called QuickSortItem mentioned by Bryce.

Also look at Bryce's example where he put the whole code together for you minus the UDF.

Copy and paste his code and the UDFs he mentioned (without changing any of the UDF code) and then run it with KiXtart 4.51 or newer.
 


BunzyBuddy
(Fresh Scripter)
2006-02-27 09:42 AM
Re: Folders sorted by size

That's exactly what I did: I copies the QuickSort UDF and Bryce's code into a new .kix document without changeing anything. Then I got this error.
This line giving me that error, you'll find it in the QuickSoft UDF.

Running Kix 4.51 I got error : Expexted ')'! in that same line....


NTDOCAdministrator
(KiX Master)
2006-02-27 09:46 AM
Re: Folders sorted by size

Okay I see now QuickSort has a dependency of QuickSortItem UDF.

Okay, make sure you have all 3 UDFs in the script or called.
 


NTDOCAdministrator
(KiX Master)
2006-02-27 09:47 AM
Re: Folders sorted by size

 
break on
$root = dirplus('C:\Program Files','/ad')

dim $folders[ubound($root)]

for $i = 0 to ubound($root)
$n = $root[$i].name
$s = val($root[$i].size)
$folders[$i] = $n,$s
next

$folders = quicksort($folders,1)

for each $item in $folders
? $item[0] " " $item[1]
next

Function DirPlus($path,optional $Options, optional $f, optional $sfflag)
If not vartype($f) DIM $f EndIf
If not vartype($sfflag) DIM $sfflag EndIf

DIM $file, $i, $temp, $item, $ex1, $mask,$mask1,$maskArray,$maskarray1,
$ex2, $code, $CodeWeight, $targetWeight, $weight, $masktrue
DIM $tarray[0]

$ex1 = SetOption(Explicit,on)
$ex2 = SetOption(NoVarsInStrings,on)
$codeWeight = 0

If not Exist($path)
$temp = SetOption(Explicit,$ex1)
$temp = SetOption(NoVarsInStrings,$ex2)
Exit @ERROR
EndIf

If not vartype($f)
$f = CreateObject("Scripting.FileSystemObject").getfolder($path)
EndIf
If @ERROR
$temp = SetOption(Explicit,$ex1)
$temp = SetOption(NoVarsInStrings,$ex2)
Exit @ERROR
EndIf

For Each $temp In Split($options,"/")
$temp=Trim($temp)
Select
Case left($temp,1) = "s"
If not vartype($sfflag)
If Val(right($temp,-1)) = 0
$sfflag = -1
Else
$sfflag = Val(right($temp,-1))
EndIf
EndIf
Case Left($temp,1) = "a"
Select
Case Right($temp,-1)="d"
$codeWeight = $codeWeight + 1
$temp = "if $file.attributes & 16 " ;"if $file.type = 'File Folder' "
Case Right($temp,-1)="-d"
$codeWeight = $codeWeight + 1
$temp = "if ($file.attributes & 16)=0 " ;"if $file.type <> 'File Folder' "
Case Right($temp,-1)="s"
$codeWeight = $codeWeight + 1
$temp = "if $file.attributes & 4 "
Case Right($temp,-1)="-s"
$codeWeight = $codeWeight + 1
$temp = "if ($file.attributes & 4)=0 "
Case Right($temp,-1)="h"
$codeWeight = $codeWeight + 1
$temp = "if $file.attributes & 2 "
Case Right($temp,-1)="-h"
$codeWeight = $codeWeight + 1
$temp = "if ($file.attributes & 2)=0 "
Case Right($temp,-1)="r"
$codeWeight = $codeWeight + 1
$temp = "if $file.attributes & 1 "
Case Right($temp,-1)="-r"
$codeWeight = $codeWeight + 1
$temp = "if ($file.attributes & 1)=0 "
Case Right($temp,-1)="a"
$codeWeight = $codeWeight + 1
$temp = "if $file.attributes & 32 "
Case Right($temp,-1)="-a"
$codeWeight = $codeWeight + 1
$temp = "if ($file.attributes & 32)=0 "
EndSelect
$code = $temp + "$weight=$weight+1 endif" +@CRLF + $code

Case Left($temp,1) = "m"
$maskarray = Split(Right($temp,-2),"|")
$codeweight = $codeweight + 1
$code = "$masktrue=0 for Each $mask in $maskarray if instr($file.name,$mask) $masktrue=1 " +
"EndIf Next If $masktrue $weight=$weight+1 endif" + @CRLF +$code
Case Left($temp,1) = "f"
$maskarray1 = Split(Right($temp,-2)," ")
$codeweight = $codeweight + 1
$code = "$masktrue=0 for Each $mask1 in $maskarray1 if substr($file.name,Instrrev($file.name,'.')+1)" +
"=$mask1 $masktrue=1 EndIf Next If $masktrue $weight=$weight+1 endif" + @CRLF +$code

EndSelect
Next
$code = "$weight = 0 $targetWeight = " + $codeweight + @CRLF + $code
$code = $code + "if $weight = $targetweight Exit 1 endif"

For Each $file In $f.subfolders
If Execute($code)
$tarray[$i] = $file
$i = $i + 1
ReDIM preserve $tarray[$i]
EndIf
If $sfflag
$temp = dirplus($file,$options,$file,$sfflag-1)
For Each $item In $temp
$tarray[$i] = $item
$i = $i + 1
ReDIM preserve $tarray[$i]
Next
EndIf
Next
For Each $file In $f.files
If Execute($code)
$tarray[$i] = $file
$i = $i + 1

ReDIM preserve $tarray[$i]
EndIf
Next

If $i
ReDIM preserve $tarray[$i-1]
$i=0
Else
$tarray = 0
EndIf

$dirplus = $tarray
$temp = SetOption(Explicit,$ex1)
$temp = SetOption(NoVarsInStrings,$ex2)
Exit @ERROR
EndFunction

function quicksort($a, optional $indexcol )
;$a array to be sorted
;$indexcol index of subitem to sort on

;$LowerIndexStack lower index stack
;$UpperIndexStack upper index stack
;$StackPointer stack pointer
;$LowerIndex lower index
;$UpperIndex upper index
;$Pivot value of pivot
;$TempSwappingValue temp variable for swapping elements
;$index stores either lower or upper index of unsorted segment of the array
;$i counter moving from lower index to the right
;$j counter moving from upper index to the left
;$LowerItem value to compare with

dim $StackSize, $StackIncr
$StackSize = 8
$StackIncr = $StackSize

dim $LowerIndexStack[$StackSize],$UpperIndexStack[$StackSize]
dim $StackPointer, $LowerIndex, $UpperIndex, $Pivot, $TempSwappingValue, $index, $i, $j, $LowerItem
dim $ExitLoop

if $indexcol
$indexcol = CStr($indexcol)
if indexcol < 0
$indexcol = 0
endif
else
$indexcol = 0
endif

$LowerIndexStack[0]=0
$UpperIndexStack[0]=UBOUND($a)
$StackPointer=0
While $StackPointer >= 0
$LowerIndex=$LowerIndexStack[$StackPointer]
$UpperIndex=$UpperIndexStack[$StackPointer]
While $LowerIndex < $UpperIndex
$Pivot=$LowerIndex+($UpperIndex-$LowerIndex)/2
$TempSwappingValue=$a[$LowerIndex]
$A[$LowerIndex]=$A[$Pivot]
$A[$Pivot]=$TempSwappingValue
$i=$LowerIndex+1
$j=$UpperIndex
$ExitLoop=0
Do
$LowerItem = QuickSortItem( $A[$LowerIndex],$indexcol )
While ($i<$j) AND ( QuickSortItem( $A[$i],$indexcol ) < $LowerItem)
$i=$i+1
Loop
While ($j>=$i) AND ($LowerItem < QuickSortItem( $A[$j],$indexcol ))
$j=$j-1
Loop
if $i>=$j
$ExitLoop=1
else
$TempSwappingValue=$A[$i]
$A[$i]=$A[$j]
$A[$j]=$TempSwappingValue
$j=$j-1
$i=$i+1
endif
Until $ExitLoop=1
$TempSwappingValue=$a[$LowerIndex]
$a[$LowerIndex]=$a[$j]
$a[$j]=$TempSwappingValue
$index=$j
if $index - $LowerIndex <= $UpperIndex - $index
if $index+1 < $UpperIndex
if $StackPointer>$StackSize
$StackSize = $StackSize + $StackIncr
Redim preserve $LowerIndexStack[$StackSize]
Redim preserve $UpperIndexStack[$StackSize]
endif

$LowerIndexStack[$StackPointer]=$index+1
$UpperIndexStack[$StackPointer]=$UpperIndex
$StackPointer=$StackPointer+1
endif
$UpperIndex=$index-1
else
if $index-1 > $LowerIndex
if $StackPointer>$StackSize
$StackSize = $StackSize + $StackIncr
Redim preserve $LowerIndexStack[$StackSize]
Redim preserve $UpperIndexStack[$StackSize]
endif

$LowerIndexStack[$StackPointer]=$LowerIndex
$UpperIndexStack[$StackPointer]=$index-1
$StackPointer=$StackPointer+1
endif
$LowerIndex=$index+1
endif
Loop
$StackPointer=$StackPointer-1
Loop
$quicksort=$a
Endfunction

Function QuickSortItem( $value, $index )
if vartype($value) & 8192
if ($index <= UBound($value))
$QuickSortItem = $value[$index]
else
$QuickSortItem = ""
endif
else
$QuickSortItem = $value
endif
endfunction


BunzyBuddy
(Fresh Scripter)
2006-02-27 09:54 AM
Re: Folders sorted by size

YES That's it !!
Now can you tell me how to sort the other way ? Biggest folder on top ?


Richard H.Administrator
(KiX Supporter)
2006-02-27 02:41 PM
Re: Folders sorted by size

Sure, just go through the array in the other direction.

Replace:
Code:
for each $item in $folders
? $item[0] " " $item[1]
next



With:
Code:
For $i = UBound($folders) To 0 Step -1
$item=$folders[$i]
$item[0]+" "+$item[1]+@CRLF
Next



BunzyBuddy
(Fresh Scripter)
2006-02-27 03:25 PM
Re: Folders sorted by size

Yes, thats works.
Is there a way to format the output in MB instead of bytes ?
My whole script is formatted with the "FormatNumber" expression while writing results to a textfile.

WRITELINE (1, $item[0] + " " + $item[1] + @CRLF)


Mart
(KiX Supporter)
2006-02-27 03:55 PM
Re: Folders sorted by size

Just divide it by 1024.

Richard H.Administrator
(KiX Supporter)
2006-02-27 05:04 PM
Re: Folders sorted by size

...and then by 1024 again.

Mart
(KiX Supporter)
2006-02-27 08:42 PM
Re: Folders sorted by size

Woops, my bad

BunzyBuddy
(Fresh Scripter)
2006-02-28 09:51 AM
Re: Folders sorted by size

When I run my script, I got all homedirs and their sizer. That's good. But is it possible to limit the number of items to, lets say 10 ? So only the top-10 of the biggest folders will be reported ?

NTDOCAdministrator
(KiX Master)
2006-02-28 10:09 AM
Re: Folders sorted by size

Yes, just use an index counter.

Richard H.Administrator
(KiX Supporter)
2006-02-28 10:09 AM
Re: Folders sorted by size

Yes.

How have you tried to do it so far?


NTDOCAdministrator
(KiX Master)
2006-02-28 10:10 AM
Re: Folders sorted by size

Also just ask up front what you really want, this is like the 2nd or 3rd request to have it do something different than you originally asked, which is okay, but asking up front and letting us know specifically what you want would save everyone time.

LonkeroAdministrator
(KiX Master Guru)
2006-02-28 10:28 AM
Re: Folders sorted by size

doc, I saved my time by not answering the first questions

BunzyBuddy
(Fresh Scripter)
2006-02-28 11:48 AM
Re: Folders sorted by size

I'm sorry, I thought my firt question was clear:

Quote:

I want to scan the size of the users HomeDirs in our HomeDirs folder, sort all folders by size and write the 3 biggest folders' name and size in a textfile.




So, now I have almost all of it, only the selection of the 10 biggest folders (okay, instead of 3) is missing.

Using counters ? I'm afraid I do not know how to do so. If I did, I wouldn't be asking on this forum, would I?


LonkeroAdministrator
(KiX Master Guru)
2006-02-28 12:03 PM
Re: Folders sorted by size

well, if you have a array having the folders, counter is the thingie inside the brackets.

thus $array[0] would give you the largest.

for $counter=0 to 9
$array[$counter] ?
next

would give you the 10 largest.


BunzyBuddy
(Fresh Scripter)
2006-02-28 12:16 PM
Re: Folders sorted by size

OK, I understand the meaning of $Counter, but I'm not sure where to put in in my script. I've tried serval places without any luck. Could you please tell me where to put int in ?


*********
break on
call 'quicksort.udf'
call 'dirplus.udf'

OPEN (1, "E:\Script\HomeSize @MDAYNO @MONTH @YEAR.txt",5)

$root = dirplus('$HomeDirsLocation','/ad')

dim $folders[ubound($root)]

for $i = 0 to ubound($root)
$n = $root[$i].name
$s = val($root[$i].size)
$folders[$i] = $n,$s
next

$folders = quicksort($folders,1)

For $i = UBound($folders) To 0 Step -1
$item=$folders[$i]
$item[0]+" "+$item[1]+@CRLF
WRITELINE (1, $item[0] + " " + FormatNumber (CDbl($item[1]/1024/1024),0) + " MB" + @CRLF)
Next

**********


LonkeroAdministrator
(KiX Master Guru)
2006-02-28 12:19 PM
Re: Folders sorted by size

well, I already gave you example but here:
For $i = UBound($folders) To 0 Step -1

instead of ubound, do $i = 9


BunzyBuddy
(Fresh Scripter)
2006-02-28 12:29 PM
Re: Folders sorted by size

I'm sorry Jooel, I replaced

For $i = UBound($folders) To 0 Step -1

by

For $i = 9 To 0 Step -1

but this gives me a result of all homedirs sizes of 0MB...


Richard H.Administrator
(KiX Supporter)
2006-02-28 12:53 PM
Re: Folders sorted by size

Try this:
Code:
$iLimit=UBound($Folders)-9
If $iLimit<9 $iLimit=UBound($Folders) EndIf
For $i = UBound($folders) To $iLimit Step -1
$item=$folders[$i]
$item[0]+" "+$item[1]+@CRLF
$=WriteLine(1, $item[0] + " " + FormatNumber (CDbl($item[1]/1024/1024),0) + " MB" + @CRLF)
Next



BunzyBuddy
(Fresh Scripter)
2006-02-28 12:59 PM
Re: Folders sorted by size

You are a scripting hero.

Now everything works exactly the way I wanted. Thank you all you guys for your help and patience !


LonkeroAdministrator
(KiX Master Guru)
2006-02-28 01:02 PM
Re: Folders sorted by size

hmm...
sorry for my ignorance.
it wasn't clear to me which way your sorted array was increasing.
specially when you were going it backwards up in the for loop, it got me confused.


BunzyBuddy
(Fresh Scripter)
2006-02-28 01:16 PM
Re: Folders sorted by size

Don't bother, you were all great help. Could not do it without you !

BunzyBuddy
(Fresh Scripter)
2006-03-23 11:44 AM
Re: Folders sorted by size

Last question:
In my script I'm first scanning all HomeDirs and writing the results to my textfile. After that I'm scanning the GroupsDirs and also writing the results to the textfile. But, when a HomeDirectory's size is bigger than one of the GroupsDirs, it appears in the GroupsDirs result list.

So, is there a command to clear the "cache" after having scanned the Homedirs ?