My favorite PowerShell one-liner

Happy Monday everyone!  I thought it might be a fun way to start the week by sharing my favorite PowerShell one-liner.  One-liners are nostalgic for me, because I learned a lot of cool programming tricks from one-liners in issues of Compute magazine a long time ago.  The PowerShell one-liners that grab my interest the most are those that can do many different things in the simplest pipeline possible.

So far, eight years into using PowerShell, this is my favorite PowerShell one-liner:

image

At first glance, can you tell what this does?  Take a minute to think about it, I’ll wait.

 

 

 

Ok, now that you’ve thought about it a bit, you might have realized that it is not that easy to figure out everything that this does, so let me break it down into parts.

gci –r -force

If your familiar with PowerShell, this part is pretty straightforward.  gci is an alias for Get-ChildItem, and this command tells PowerShell to get a recursive (-r) directory listing of all files and folders, including any hidden files or folders (-force), starting from the current location.

measure -sum PSIsContainer,Length -ea 0

measure is an alias for Measure-Object, a cmdlet that can perform calculations on a collection of objects that it is passed from a pipeline.  In this case, we’re going to aggregate (-sum) two values from properties in this collection: PSIsContainer and Length. We’re also going to hide any errors we get from trying to access folders that we don’t have access to (-ea 0).  How Measure-Object measures the objects it receives is the most interesting part of this pipeline.

You can probably guess why we would want to calculate the sum of the Length property, but why would you want to calculate the sum of the PSIsContainer property?  PSContainer is a boolean value that indicates whether or not an item returned from Get-ChildItem is a container.  A value of $true indicates it is a folder, and a value of $false indicates it is a file.  When you calculate the sum of a bunch of boolean values in PowerShell, PowerShell first converts those boolean values into their integer equivalent.  $false implictly converts into a value of 0, and $true implicitly converts into a value of 1.  Given this is the case, by aggregating the PSIsContainer property, you’re effectively calculating a sum of the number of containers in the result set.

$di,$fi =

PowerShell allows you to assign a multi-valued result set to different variables by separating the variables with a comma.  In such an assignment, the first object returned will be assigned to the first variable, the second assigned to the second variable, and so on until the last variable which will contain all remaining objects.  In this case, we’re assigning two variables, and each will contain a single value.  Since we’re aggregating two properties (PSIsContainer and Length), Measure-Object will return two objects containing measurement information: one for PSIsContainer and one for Length.  The measurement information for PSIsContainer will be assigned to $di and the measurement information for Length will be assigned to $fi.

Also, in addition to calculating the aggregate for the two properties, Measure-Object also counts the number of objects that it processes to perform that calculation and includes that count in the result as well.  In cases where an object does not have a property that is being measured, that object will not be included in the count, so folders, which do not have a Length property, will not influence the values returned in the second measurement information object that is assigned to $fi.

Putting it all together

When I run the aforementioned one-liner on my PowerShell folder, here are the values I get from $di and $fi, respectively:

Count    : 6516
Average  :
Sum      : 2012
Maximum  :
Minimum  :
Property : PSIsContainer

Count    : 4504
Average  :
Sum      : 917710488
Maximum  :
Minimum  :
Property : Length

For the $di object, the Sum property identifies how many directories were found in the search.  This was determined by aggregating the integer value of the PSIsContainer property on the objects that were measured.  The Count property identifies how many items altogether were processed (directories and files, both of which have a PSIsContainer property).

For the $fi object, the Sum property identifies the total size of all files that were found in the search, and the Count property identifies how many files were found in the search.

Put this all together, and you have a PowerShell one-liner that gives you folder stats, identifying the number of files and folders in a folder as well as the total size of all files in that folder.  Neat, huh?  I think the reason why I like this PowerShell one-liner the most is because it demonstrates how a little creativity can be applied to get useful information that is not available in a native cmdlet from several sources in a simple and elegant manner.

What’s your favorite one-liner, and why?

Maybe I should start a meme with this.  Jeffrey Hicks, Shay Levy, Ed Wilson, June Blender, and Hal Rottenberg, tag, you’re it! Smile

Kirk out.

Advertisements

11 thoughts on “My favorite PowerShell one-liner

  1. I’m having trouble coming up with an all-time favorite but here’s one I’ve been using a lot in the last few months:

    Get-xDscOperation -Newest 3 | select -ExpandProperty allevents | select timecreated, message | Out-GridView

    If it’s not obvious to you what this does, it pops up a searchable window that has all of the events from the last 3 times PowerShell Desired State Configuration (DSC) has checked configuration data or applied changes.

    I love using Out-GridView for this because I can quickly use the filter box to search for specific things in the logs. You can also view the entire message field which in the console can sometimes be a pain with long entries.

    Like

  2. I am getting this when I run the line:
    gci -r -Force | measure -Sum PSIsContainer,lenght -ea 0
    Count : 114
    Average :
    Sum : 2
    Maximum :
    Minimum :
    Property : PSIsContainer

    SO then when I run:
    $di,$fi = gci -r -Force | measure -Sum PSIsContainer,lenght -ea 0
    and check the variables:
    $di:
    Count : 114
    Average :
    Sum : 2
    Maximum :
    Minimum :
    Property : PSIsContainer

    and $fi is empty? what did I miss?
    Thank you

    Like

  3. I don’t see what the difference is? Maybe someone can help?
    gci –r -force | measure -sum PSIsContainer, Length -ea 0 #working
    gci -r -Force | measure -sum PSIsContainer, Lenght -ea 0 #Not Working

    Like

  4. Nice! That would probably a good challenge to put on Code-Golf. And it probably points to something that should be improved in PowerShell Core — I never liked that Invoke-History takes pipeline input but only accepts a single history command.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s