sysinternals du.exe in PowerShell (can you help me?)

by Vern Anderson at 2012-08-16 07:27:47

So this is more of a project I’ve been working on but my skills are not quite that advanced yet. Since the forums are getting a lot of attention right now I thought I’d throw it out to the group. basically sysinternals has the command line tool DU.exe. DU = Disk Usage

http://technet.microsoft.com/en-us/sysi … 96651.aspx

The functionality I want is like what "du -L 1" does it collects a list of all the sub folders and the root of the current folder then it re curses through the list of folders and measures the sum of all it’s children in KB. And reports that next to the name. The results look like this…


11,930,536 C:<br> 10,875,794 C:\Windows
238,281 C:\Users
229,197 C:\Program Files (x86)
178,145 C:\ProgramData
168,344 C:\Recovery
113,741 C:\rs-pkgs
104,280 C:\Program Files
14,252 C:\Boot
7,765 C:\DRV
347 C:\inetpub
2 C:$Recycle.Bin
0 C:\PerfLogs
0 C:\iislogs

…I know from recent Ed Wilson blogs and some other scripts that were popping up on how to measure a folder’s total size (Length) of that folder.

http://blogs.technet.com/b/heyscripting … shell.aspx

Get-ChildItem -Path C:\ | where {($.psiscontainer)}

But I want it to have a for loop or something that repeats the "folder size" function for each folder found in the current path. just like DU.exe but done with PowerShell. I will eventually figure it out but since the challenge went out on twitter to post some questions and since the forums are getting some good attention I figured why not throw it out there…Thanks in advance!

This is what I have so far but the output is ugly…

==========================================================================================
$home = Get-Location
get-childitem | foreach-object -process {
if ($
.PSIsContainer -eq $True)
{
Set-Location $.FullName -PassThru ; Get-ChildItem -Recurse | Measure-Object -Sum Length | Select-Object Count,Sum
Set-Location $home
}
else
{
Get-ChildItem | Where-Object {$
.PSIsContainer -ne $true} | Select-Object Name,Length
}
}
==========================================================================================

-VERN
by DonJ at 2012-08-16 07:48:16
You basically have to write a recursive function.

So, you write a function that accepts a folder name. It enumerates each subfolder, and then calls itself for each one of those.

Alternately, in v3 at least, you’d do something like GCI -recurse -folder (although -folder might be -directory; don’t have it in front of me right now). That’ll produce a list of subfolders in the tree. Those can then be fed to a function that gets their size and displays whatever.
by sqlchow at 2012-08-16 12:17:32
I believe your main concern is to recursing through the result set. As luck would have it, determining folder sizes was one of the events in Powershell scripting games this year. The solution can easily be adapted to your problem.

And here is the expert commentary provided by Chad Miller :
http://blogs.technet.com/b/heyscriptingguy/archive/2012/04/19/expert-commentary-2012-scripting-games-advanced-event-4.aspx


If you have further questions on this topic, kindly post them here.
by Vern Anderson at 2012-08-17 17:25:09
Thank you for your response wow I see what I’m missing in the advanced games. I was in the beginner this last go round.

Your google foo was better than mine so I started searching with BING and also found these 2 as well.

http://gallery.technet.microsoft.com/sc … r-e4b05c1d

http://poshcode.org/721

I still want to learn it though and maybe make it without cheating so to speak. Thank you so much for your response!

-VERN
by poshoholic at 2012-08-17 19:50:19
One tip while you work this out: if all you want is to get the size of child folders inside a specific directory, you don’t actually need to create a recursive function to do this. Get-ChildItem has a -Recurse parameter that will do all of the recursion you need, allowing you to focus on getting the immediate children and then determining their size.

Of those two samples you found, the PoshCode one is of much better quality. The one on the gallery is missing a very important detail (he forgot to use the -Force). :wink:
by Vern Anderson at 2012-08-18 10:21:03
Agreed poshohilic if it had a -Descending parameter it would be perfect! (Well that and then automatically elevate to admin) :wink:

However I will still continue working on my own so I can learn too. =)

-VERN
by Vern Anderson at 2012-09-11 17:15:56
Found another great one…

http://blogs.technet.com/b/heyscripting … shell.aspx

-VERN
by Vern Anderson at 2012-10-08 13:56:38
#Made some more progress today

$ErrorActionPreference = ‘SilentlyContinue’
$backhome = Get-Location
get-childitem | foreach-object -process {
if ($.PSIsContainer -eq $True){
Set-Location $
.Name ;
$foldername = Get-Location
$dirsize = [math]::round((Get-ChildItem -Recurse | Measure-Object -Sum Length).Sum/1MB,2)
"$dirsize MB t t $foldername"
Set-Location $backhome
}} | Sort-Object -Descending
by LarryWeiss at 2012-10-09 12:58:06
Do you need this to be exclusively coded in PowerShell ?
I have a quick-and-dirty solution that punts out to cmd.exe for the heavy lifting:

dir |
? { ${}.psIsContainer } |
% {
‘’ + ((@(cmd /c dir /s ${
}.name)[-2])[25..38] -join ‘’) + ’ ’ + ${}.name
}

There’s some "parse and pray" going on, but it gets the numbers for one level deep at the current directory.
by Vern Anderson at 2012-10-10 10:03:45
Hey Larry,

Yes I am trying to stay pure PowerShell. However thank you for sharing this with us. =)
by Vern Anderson at 2012-11-07 12:30:24
#OK I’m pretty much done with this as far as I want to take it…

$location = Get-Location
Get-ChildItem $location | Where-Object { $
.PSIScontainer } |
Select @{Name="Size (MB)";Expression={(Get-ChildItem $.Fullname -Recurse |
Measure-Object -Property Length -Sum).Sum/1MB}},Fullname | Sort-Object "Size (MB)" -Descending |
Select-Object @{Name="Size (MB)";Expression={"{0:0,0.00}" -f ($
."Size (MB)")}},Fullname |
Format-Table -AutoSize