Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

How can I modify the default ls (Get-ChildItem) in PowerShell so that it displays human-readable file sizes, like ls -h on a *nix machine?

ls -lh does simple logic with the file size, so that it shows bytes for really small files, kilobytes for files over 1K (with one decimal place if it's under 10K), and megabytes for files over 1M (with one decimal place if it's under 10MB).

share|improve this question
add comment

3 Answers

up vote 7 down vote accepted

try this

PS> gc c:\scripts\type\shrf.ps1xml

<Types>
<Type>
  <Name>System.IO.FileInfo</Name>
   <Members>
      <ScriptProperty>
          <Name>FileSize</Name>
          <GetScriptBlock>
             switch($this.length) {
               { $_ -gt 1tb } 
                      { "{0:n2} TB" -f ($_ / 1tb) }
               { $_ -gt 1gb } 
                      { "{0:n2} GB" -f ($_ / 1gb) }
               { $_ -gt 1mb } 
                      { "{0:n2} MB " -f ($_ / 1mb) }
               { $_ -gt 1kb } 
                      { "{0:n2} KB " -f ($_ / 1Kb) }
               default  
                      { "{0} B " -f $_} 
             }      
          </GetScriptBlock>
     </ScriptProperty>   
  </Members>
</Type>
</Types>

PS> Update-TypeData -AppendPath c:\scripts\type\shrf.ps1xml -verbose
PS> get-childItem $env:windir  | select Name,FileSize,length
PS> # you can paste this in your profile
PS> 

you can also use dynamic type data with PS3:

   PS> Update-TypeData -TypeName System.IO.FileInfo -MemberName FileSize -MemberType ScriptProperty -Value { 

    switch($this.length) {
               { $_ -gt 1tb } 
                      { "{0:n2} TB" -f ($_ / 1tb) }
               { $_ -gt 1gb } 
                      { "{0:n2} GB" -f ($_ / 1gb) }
               { $_ -gt 1mb } 
                      { "{0:n2} MB " -f ($_ / 1mb) }
               { $_ -gt 1kb } 
                      { "{0:n2} KB " -f ($_ / 1Kb) }
               default  
                      { "{0} B " -f $_} 
             }      

 } -DefaultDisplayPropertySet Mode,LastWriteTime,FileSize,Name
share|improve this answer
    
I really like building it in as an extra property. The only problem using the PS3 version is I get: Update-TypeData : Error in TypeData "System.IO.FileInfo": The member DefaultDisplayPropertySet is already present. Running latest PS3 full release from 9/4. –  Thomas G. Mayfield Sep 5 '12 at 15:24
add comment

First, create the following function:

Function Format-FileSize() {
    Param ([int]$size)
    If     ($size -gt 1TB) {[string]::Format("{0:0.00} TB", $size / 1TB)}
    ElseIf ($size -gt 1GB) {[string]::Format("{0:0.00} GB", $size / 1GB)}
    ElseIf ($size -gt 1MB) {[string]::Format("{0:0.00} MB", $size / 1MB)}
    ElseIf ($size -gt 1KB) {[string]::Format("{0:0.00} kB", $size / 1KB)}
    ElseIf ($size -gt 0)   {[string]::Format("{0:0.00} B", $size)}
    Else                   {""}
}

You can then pipe the output of Get-ChildItem through Select-Object and use a calculated property to format the filesize:

Get-ChildItem | Select-Object Name, @{Name="Size";Expression={Format-FileSize($_.Length)}}

The function can of course be improved to account for sizes in the PB range and more, or to vary the number of decimal points as necessary.

share|improve this answer
    
Is there a reason that an alias can't be created to do this as getshilditem itself (check is there is an -lh flag or something, and if not, then just use Get-ChildItem, else use this) –  soandos Aug 31 '12 at 20:05
    
You can't create aliases for piped commands, nor override the default aliases. If you can live with using an alias like ls2, try creating another function that does the logic you described based on a parameter, then add an alias for it. See here for more information on creating aliases. –  Indrek Aug 31 '12 at 20:24
    
Alternatively, look into custom formatting files to extend cmdlet output. See this forum topic for an example. Also, to make the formatting function persist through PowerShell sessions, add it to your profile file (see Get-Variable profile for its location). –  Indrek Aug 31 '12 at 20:31
add comment

Something like the following for listing just file sizes. Yes it is a bit sore on the eyes but it manages to get the job done.

For converting to KB:

ls | Select-Object Name, @{Name="KiloBytes";Expression={$_.Length / 1KB}}

For converting to MB:

ls | Select-Object Name, @{Name="MegaBytes";Expression={$_.Length / 1MB}}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.