Windows Vista Forums

Get dirs from n

  1. #1


    William Stacey [C# MVP] Guest

    Get dirs from n

    How to recurse dirs from some root and return only director name and size
    with a sort? TIA

    --
    William Stacey [C# MVP]






      My System SpecsSystem Spec

  2. #2


    dreeschkind Guest

    RE: Get dirs from n

    This is my solution. I added the full path name to the output, too.

    # This may take a while due to sorting/formatting...
    PS> gci -recurse c:\windows | where { $_.psiscontainer } |
    foreach {
    $obj = 1 | select name, path, sum_length;
    $obj.name = $_.name; $obj.path = $_.fullname;
    $temp = gci -recurse $_.fullname | where {!($_.psiscontainer)} |
    measure-object length -sum;
    if ($temp -ne $null) {$obj.sum_length = $temp.sum}
    else {$obj.sum_length = 0};
    $obj
    } | sort sum_length | ft -auto


    sample output (sorting left out):


    name path
    sum_length
    ---- ----
    ----------
    ADDINS C:\windows\ADDINS
    791
    AppPatch C:\windows\AppPatch
    5228016
    ASSEMBLY C:\windows\ASSEMBLY
    564737965
    Config C:\windows\Config
    0
    Connection Wizard C:\windows\Connection W...
    0
    Corel C:\windows\Corel
    536633
    ....

    --
    greetings
    dreeschkind


    "William Stacey [C# MVP]" wrote:

    > How to recurse dirs from some root and return only director name and size
    > with a sort? TIA
    >
    > --
    > William Stacey [C# MVP]
    >
    >
    >
    >


      My System SpecsSystem Spec

  3. #3


    Keith Hill [MVP] Guest

    Re: Get dirs from n

    "William Stacey [C# MVP]" <william.stacey@gmail.com> wrote in message news:OPkSbZjFHHA.1804@TK2MSFTNGP02.phx.gbl...
    > How to recurse dirs from some root and return only director name and size
    > with a sort? TIA


    Here's another approach that isn't as a terse as dreeschkind's solution but it is perhaps easier to follow. :-)
    It also sorts.


    --------------------------------------------------------------------------------

    # GetFolderSize.ps1

    param([string]$path=(get-location))

    $folderSizes = @{}

    function processFile($path) {
    $parent = split-path $path -parent
    $fileSize = (get-item $path -ea SilentlyContinue).Length
    $folderSizes[$parent] += $fileSize
    }

    function processFolder($path) {
    $name = (get-item $path).FullName
    $folderSizes[$name] = 0
    foreach ($item in (get-childitem $path -ea SilentlyContinue)) {
    if ($item.PSIsContainer) {
    $folderPath = $item.FullName
    processFolder($folderPath)
    $parent = split-path $folderPath
    if ($parent -ne $null) {
    $folderSizes[$parent] += $folderSizes[$folderPath]
    }
    }
    else {
    processFile($item.FullName)
    }
    }
    }

    # Execution starts here
    processFolder($path)
    $folderSizes.GetEnumerator() | select Key,Value | sort Value -desc |
    %{"{0,15:N0} {1}" -f $_.Value, $_.Key}

    --------------------------------------------------------------------------------


    One limitation of this approach is that it uses recursion and the recursion depth in PoSh is limited to 100. So if you have directories nested more than 100 deep this will bomb unless you can bump the recursion limit. I seem to recall that there might be a way to do that via a preference variable but I don't remember what it is. Anyone remember?

    --
    Keith

      My System SpecsSystem Spec

  4. #4


    Jacques Barathon [MS] Guest

    Re: Get dirs from n

    "William Stacey [C# MVP]" <william.stacey@gmail.com> wrote in message
    news:OPkSbZjFHHA.1804@TK2MSFTNGP02.phx.gbl...
    > How to recurse dirs from some root and return only director name and size
    > with a sort? TIA


    Not thoroughly tested, but this one-liner should do the trick:

    dir -rec|?{$_.PSIsContainer}|select fullname,@{n="Size";e={(dir
    $_.fullname|measure length -sum).sum}}|sort size -desc

    If you want to display the directory name only (instead of its full path
    name), replace "select fullname" with "select name".

    Jacques


      My System SpecsSystem Spec

  5. #5


    Jacques Barathon [MS] Guest

    Re: Get dirs from n

    "Jacques Barathon [MS]" <jbaratho@online.microsoft.com> wrote in message
    news:%23EPBmkoFHHA.5104@TK2MSFTNGP03.phx.gbl...
    > "William Stacey [C# MVP]" <william.stacey@gmail.com> wrote in message
    > news:OPkSbZjFHHA.1804@TK2MSFTNGP02.phx.gbl...
    >> How to recurse dirs from some root and return only director name and size
    >> with a sort? TIA

    >
    > Not thoroughly tested, but this one-liner should do the trick:
    >
    > dir -rec|?{$_.PSIsContainer}|select fullname,@{n="Size";e={(dir
    > $_.fullname|measure length -sum).sum}}|sort size -desc
    >
    > If you want to display the directory name only (instead of its full path
    > name), replace "select fullname" with "select name".


    Addendum: if you want to capture the size of the entire content of each
    directory (including the subdirectories etc), you will have to add a "-rec"
    parameter to the second dir statement as well:

    dir -rec|?{$_.PSIsContainer}|select fullname,@{n="Size";e={(dir
    $_.fullname -rec|measure length -sum).sum}}|sort size -desc

    Jacques


      My System SpecsSystem Spec

  6. #6


    Keith Hill [MVP] Guest

    Re: Get dirs from n

    Here's a more robust version. Note the use of -Force on Get-ChildItem to get the folder sizes of hidden folders:


    --------------------------------------------------------------------------------

    param([string]$path=(get-location))

    $dirSize = @{}

    function processFile($path) {
    $parent = split-path $path -parent
    $fileSize = (get-item -LiteralPath $path -Force -ea Continue).Length
    $dirSize[$parent] += $fileSize
    }

    function processDirectory([string]$path) {
    $dirSize[$path] = 0
    $items = get-childitem -LiteralPath $path -Force -ea Continue | sort @{e={$_.PSIsContainer}}
    if ($items -eq $null) {
    return
    }
    foreach ($item in $items) {
    if ($item.PSIsContainer) {
    processDirectory($item.FullName)
    $dirSize[$path] += $dirSize[$item.FullName]
    }
    else {
    processFile($item.FullName)
    }
    }
    }

    # Execution starts here
    $rpath = Resolve-Path $path
    processDirectory($rpath)
    $dirSize.GetEnumerator() | select Key,Value | sort Value -desc |
    %{"{0,15:N0} {1}" -f $_.Value, $_.Key}

    --------------------------------------------------------------------------------


    Turns out that you have to use -LiteralPath to handle dir names that use the special PoSh characters like $, [, ], etc. BTW this took about 21 minutes to get folder sizes for almost every folder on my system (16, 984 folders). Turns out that there are some folders that my security principal cant' read:

    147> measure-command { C:\bin\GetDirectorySize.ps1 C:\ | out-string -width 260 >
    dirlist.txt }
    Get-ChildItem : Access to the path 'C:\System Volume Information' is denied.
    At C:\bin\GetDirectorySize.ps1:23 char:24
    + $items = get-childitem <<<< -LiteralPath $path -Force -ea Continue | sor
    t @{e={$_.PSIsContainer}}
    Get-ChildItem : Access to the path 'C:\Program Files\Microsoft Windows OneCare
    Live\ClientSD' is denied.
    At C:\bin\GetDirectorySize.ps1:23 char:24
    + $items = get-childitem <<<< -LiteralPath $path -Force -ea Continue | sor
    t @{e={$_.PSIsContainer}}

    Days : 0
    Hours : 0
    Minutes : 20
    Seconds : 31
    Milliseconds : 102
    Ticks : 12311028557
    TotalDays : 0.0142488756446759
    TotalHours : 0.341973015472222
    TotalMinutes : 20.5183809283333
    TotalSeconds : 1231.1028557
    TotalMilliseconds : 1231102.8557


    104,204,662,579 C:\
    34,037,812,872 C:\Virtual Machines
    26,459,581,836 C:\Documents and Settings
    25,178,776,785 C:\Documents and Settings\Keith
    24,045,391,046 C:\Program Files
    22,302,532,331 C:\Documents and Settings\Keith\My Documents
    15,809,772,658 C:\Documents and Settings\Keith\My Documents\My Videos
    15,556,241,154 C:\Virtual Machines\Orcas October CTP
    11,673,828,372 C:\Virtual Machines\Windows XP Pro
    ....
    0 C:\Documents and Settings\Keith\My Documents\Visual Studio Projects\WindowsApplication2\ClassLibrary1\obj\Debug\TempPE
    0 C:\Documents and Settings\Keith\Application Data\Identities
    0 C:\Documents and Settings\Keith\My Documents\Visual Studio Projects\XmlDomConsole\obj\Debug\TempPE
    0 C:\WINDOWS\msapps\msinfo
    0 C:\Documents and Settings\Keith\My Documents\SQL Server Management Studio Express\Projects
    0 C:\Documents and Settings\Keith\My Documents\Visual Studio Projects\VSNUnit\SampleAll\obj\Debug\temp

    --
    Keith



      My System SpecsSystem Spec

  7. #7


    Keith Hill [MVP] Guest

    Re: Get dirs from n

    And here's a filter version that is more PoSh like in that it adds a Length NoteProperty to directories. Then you can use the PoSh utilities cmdlets to sort the directories by size:


    --------------------------------------------------------------------------------

    filter AddDirectorySize {
    function processFile([string]$path) {
    $fileSize = (get-item -LiteralPath $path -Force -ea Continue).Length
    $script:dirSize += $fileSize
    }

    function processDirectory([string]$path) {
    $items = get-childitem -LiteralPath $path -Force -ea Continue | sort @{e={$_.PSIsContainer}}
    if ($items -eq $null) {
    return
    }
    foreach ($item in $items) {
    if ($item.PSIsContainer) {
    processDirectory($item.FullName)
    }
    else {
    processFile($item.FullName)
    }
    }
    }

    if ($_ -is [System.IO.DirectoryInfo]) {
    $script:dirSize = 0
    processDirectory($_.FullName)
    Add-Member NoteProperty Length $dirSize -InputObject $_
    }
    $_
    }

    --------------------------------------------------------------------------------


    Just include this script in your profile or put it in a file and dot source it. Then try this:

    gci . -rec | AddDirectorySize | sort Length

    In fact, if you just do this you will notice that the dirs now display their length:

    196> dir $env:SystemRoot | AddDirectorySize


    Directory: Microsoft.PowerShell.Core\FileSystem::C:\WINDOWS


    Mode LastWriteTime Length Name
    ---- ------------- ------ ----
    d---- 3/23/2006 4:33 PM 0 addins
    d---- 11/3/2006 10:02 PM 5228016 AppPatch
    d-r-s 11/15/2006 10:29 PM 535950133 assembly
    d---- 3/23/2006 4:33 PM 0 Config
    d---- 3/23/2006 4:33 PM 0 Connection Wizard
    d---- 3/24/2006 12:03 AM 307984 Cursors
    d---- 3/26/2006 2:26 AM 894490 Debug
    d---- 6/19/2006 11:45 PM 6664704 Downloaded Installations
    d---s 11/25/2006 11:39 PM 1458389 Downloaded Program Files
    d---- 10/11/2006 4:18 PM 424488 DPDrv
    d---- 3/23/2006 4:33 PM 91293485 Driver Cache
    d---- 3/23/2006 4:37 PM 28672 ehome
    d-r-s 11/14/2006 11:50 PM 86014943 Fonts

    Note: this can significantly slow down the output of dir/Get-ChildItem. Only use the filter if you really need the dir sizes.

    --
    Keith

      My System SpecsSystem Spec

  8. #8


    Jacques Barathon [MS] Guest

    Re: Get dirs from n

    Following Keith's line of thought, I have modified my version so it can be
    used as a filter:

    filter add-dirlength ([switch]$recurse, [switch]$force) {
    if ($_.PSIsContainer) {
    $dirlength = (dir $_.fullname -rec:$recurse -force:$force | measure
    length -sum).sum
    $_ | add-member NoteProperty Length $dirlength -passthru
    }
    else {
    $_
    }
    }

    Usage:
    dir | add-dirlength [-recurse] [-force]

    The main difference with Keith's version is that I do not translate empty
    lengths to 0. Empty length means there is no file whereas 0 might be due to
    one or several zero-length files.

    Jacques

    "Jacques Barathon [MS]" <jbaratho@online.microsoft.com> wrote in message
    news:uOqXryoFHHA.960@TK2MSFTNGP04.phx.gbl...
    > "Jacques Barathon [MS]" <jbaratho@online.microsoft.com> wrote in message
    > news:%23EPBmkoFHHA.5104@TK2MSFTNGP03.phx.gbl...
    >> "William Stacey [C# MVP]" <william.stacey@gmail.com> wrote in message
    >> news:OPkSbZjFHHA.1804@TK2MSFTNGP02.phx.gbl...
    >>> How to recurse dirs from some root and return only director name and
    >>> size
    >>> with a sort? TIA

    >>
    >> Not thoroughly tested, but this one-liner should do the trick:
    >>
    >> dir -rec|?{$_.PSIsContainer}|select fullname,@{n="Size";e={(dir
    >> $_.fullname|measure length -sum).sum}}|sort size -desc
    >>
    >> If you want to display the directory name only (instead of its full path
    >> name), replace "select fullname" with "select name".

    >
    > Addendum: if you want to capture the size of the entire content of each
    > directory (including the subdirectories etc), you will have to add a
    > "-rec" parameter to the second dir statement as well:
    >
    > dir -rec|?{$_.PSIsContainer}|select fullname,@{n="Size";e={(dir
    > $_.fullname -rec|measure length -sum).sum}}|sort size -desc
    >
    > Jacques



      My System SpecsSystem Spec

  9. #9


    Jacques Barathon [MS] Guest

    Re: Get dirs from n

    Correcting a bug which would throw an error when the filter non-recursively
    scans a folder that does not contain any file and contains at least one
    folder:

    filter add-dirlength ([switch]$recurse, [switch]$force) {
    if ($_.PSIsContainer) {
    $dirlength = (dir $_.fullname -rec:$recurse -force:$force | ?
    {!$_.PSIsContainer} | measure length -sum).sum
    $_ | add-member NoteProperty Length $dirlength -passthru
    }
    else {
    $_
    }
    }

    Jacques

    "Jacques Barathon [MS]" <jbaratho@online.microsoft.com> wrote in message
    news:%23GvqRGvFHHA.1912@TK2MSFTNGP03.phx.gbl...
    > Following Keith's line of thought, I have modified my version so it can be
    > used as a filter:
    >
    > filter add-dirlength ([switch]$recurse, [switch]$force) {
    > if ($_.PSIsContainer) {
    > $dirlength = (dir $_.fullname -rec:$recurse -force:$force | measure
    > length -sum).sum
    > $_ | add-member NoteProperty Length $dirlength -passthru
    > }
    > else {
    > $_
    > }
    > }
    >
    > Usage:
    > dir | add-dirlength [-recurse] [-force]
    >
    > The main difference with Keith's version is that I do not translate empty
    > lengths to 0. Empty length means there is no file whereas 0 might be due
    > to one or several zero-length files.
    >
    > Jacques
    >
    > "Jacques Barathon [MS]" <jbaratho@online.microsoft.com> wrote in message
    > news:uOqXryoFHHA.960@TK2MSFTNGP04.phx.gbl...
    >> "Jacques Barathon [MS]" <jbaratho@online.microsoft.com> wrote in message
    >> news:%23EPBmkoFHHA.5104@TK2MSFTNGP03.phx.gbl...
    >>> "William Stacey [C# MVP]" <william.stacey@gmail.com> wrote in message
    >>> news:OPkSbZjFHHA.1804@TK2MSFTNGP02.phx.gbl...
    >>>> How to recurse dirs from some root and return only director name and
    >>>> size
    >>>> with a sort? TIA
    >>>
    >>> Not thoroughly tested, but this one-liner should do the trick:
    >>>
    >>> dir -rec|?{$_.PSIsContainer}|select fullname,@{n="Size";e={(dir
    >>> $_.fullname|measure length -sum).sum}}|sort size -desc
    >>>
    >>> If you want to display the directory name only (instead of its full path
    >>> name), replace "select fullname" with "select name".

    >>
    >> Addendum: if you want to capture the size of the entire content of each
    >> directory (including the subdirectories etc), you will have to add a
    >> "-rec" parameter to the second dir statement as well:
    >>
    >> dir -rec|?{$_.PSIsContainer}|select fullname,@{n="Size";e={(dir
    >> $_.fullname -rec|measure length -sum).sum}}|sort size -desc
    >>
    >> Jacques

    >



      My System SpecsSystem Spec

  10. #10


    William Stacey [C# MVP] Guest

    Re: Get dirs from n

    Very cool Jacques! I figured there was a 1 liner. How might I add the
    current dir totals into that stream?
    For example, if I am in Temp, I would like to see.

    c:\temp 100000 # the total of just the files in temp
    c:\temp\junk 100 # the total of the files in temp\junk
    c:\temp\junk\D1 10
    ....

    Your solution works great, but I don't get Temp itself - only lower. And to
    get temp, I would need to start at root. Thanks much.

    --
    William Stacey [C# MVP]

    "Jacques Barathon [MS]" <jbaratho@online.microsoft.com> wrote in message
    news:uOqXryoFHHA.960@TK2MSFTNGP04.phx.gbl...
    | "Jacques Barathon [MS]" <jbaratho@online.microsoft.com> wrote in message
    | news:%23EPBmkoFHHA.5104@TK2MSFTNGP03.phx.gbl...
    | > "William Stacey [C# MVP]" <william.stacey@gmail.com> wrote in message
    | > news:OPkSbZjFHHA.1804@TK2MSFTNGP02.phx.gbl...
    | >> How to recurse dirs from some root and return only director name and
    size
    | >> with a sort? TIA
    | >
    | > Not thoroughly tested, but this one-liner should do the trick:
    | >
    | > dir -rec|?{$_.PSIsContainer}|select fullname,@{n="Size";e={(dir
    | > $_.fullname|measure length -sum).sum}}|sort size -desc
    | >
    | > If you want to display the directory name only (instead of its full path
    | > name), replace "select fullname" with "select name".
    |
    | Addendum: if you want to capture the size of the entire content of each
    | directory (including the subdirectories etc), you will have to add a
    "-rec"
    | parameter to the second dir statement as well:
    |
    | dir -rec|?{$_.PSIsContainer}|select fullname,@{n="Size";e={(dir
    | $_.fullname -rec|measure length -sum).sum}}|sort size -desc
    |
    | Jacques
    |



      My System SpecsSystem Spec

Page 1 of 2 12 LastLast
Get dirs from n

Similar Threads
Thread Thread Starter Forum Replies Last Post
File Share Contents Limit (175 dirs)? Curt Koppang Vista networking & sharing 0 15 Jun 2008