Book Image

PowerShell: Automating Administrative Tasks

By : Michael Shepard, Chendrayan Venkatesan, Sherif Talaat, Brenton J.W. Blawat
Book Image

PowerShell: Automating Administrative Tasks

By: Michael Shepard, Chendrayan Venkatesan, Sherif Talaat, Brenton J.W. Blawat

Overview of this book

Are you tired of managing Windows administrative tasks manually and are looking to automate the entire process? If yes, then this is the right course for you. This learning path starts your PowerShell journey and will help you automate the administration of the Windows operating system and applications that run on Windows. It will get you up and running with PowerShell, taking you from the basics of installation to writing scripts and performing web server automation. You will explore the PowerShell environment and discover how to use cmdlets, functions, and scripts to automate Windows systems. The next installment of the course focuses on gaining concrete knowledge of Windows PowerShell scripting to perform professional-level scripting. The techniques here are packed with PowerShell scripts and sample C# code to automate tasks. You will use .NET classes in PowerShell and C# to manage Exchange Online. In the final section, you will delve into real-world examples to learn how to simplify the management of your Windows environment. You will get to grips with PowerShell’s advanced functions and how to most effectively administer your system. This Learning Path combines some of the best that Packt has to offer in one complete, curated package. It includes content from the following Packt products: [*] Getting Started with PowerShell by Michael Shepard [*] Windows PowerShell for .Net Developers Second Edition by Chendrayan Venkatesan and Sherif Talaat [*] Mastering Windows PowerShell Scripting by Brenton J.W. Blawat
Table of Contents (6 chapters)

Chapter 4. Life on the Assembly Line

The object-oriented pipeline is one of the distinctive features of the PowerShell environment. The ability to refer to properties of arbitrary objects without parsing increases the expressiveness of the language and allows you to work with all kinds of objects with ease.

In this chapter, we will cover the following topics:

  • How the pipeline works
  • Some of the most common cmdlets to deal with data on the pipeline:
    • Sort-Object
    • Where-Object
    • Select-Object
    • Group-Object

The pipeline as an assembly line

The pipeline in PowerShell is a mechanism to get data from one command to another. Simply put, the data that is output from the first command is treated as input to the next command in the pipeline. The pipeline isn't limited to two commands, though. It can be extended practically as long as you like, although readability would suffer if the line got too long.

Here is a simple pipeline example:

The pipeline as an assembly line

Tip

In this example, I've used some common aliases for cmdlets (where, select) to keep the line from wrapping. I'll try to include aliases when I mention cmdlets, but if you can't figure out what a command is referring to, remember you can always use Get-Command to find out what is going on. For example, Get-Command where tells you Where is an alias for Where-Object. In this case, select is an alias for Select-Object.

The execution of this pipeline can be thought of in the following sequence:

  • Get the list of services
  • Choose the services that have the Running status
  • Select the first five services
  • Output the Name and Display Name of each one

Even though this is a single line, it shows some of the power of PowerShell. The line is very expressive, doesn't include a lot of extra syntactic baggage, and doesn't even require any variables. It also doesn't use explicit types or loops. It is a very unexceptional bit of PowerShell code, but this single line represents logic that would take several lines of code in a traditional language to express.

This isn't your DOS or Linux pipeline

DOS and Linux (and Unix, for that matter) have had pipes for a long time. Pipes in these systems work similar to how PowerShell pipes work on one level. In all of them, output is streamed from one command to the next. In other shells, though, the data being passed is simple, flat text.

For a command to use the text, it either needs to parse the text to get to the interesting bits, or it needs to treat the entire output like a blob. Since Linux and Unix use text-based configurations for most operating system functions, this makes sense. A wide range of tools to parse and find substrings is available in these systems, and scripting can be very complex.

Objects at your disposal

In Windows, however, there aren't a lot of text-based configurations. Most components are managed using the Win32 or .NET APIs. PowerShell is built upon the .NET framework and leverages the .NET object model instead of using text as the primary focus. As data in the pipeline is always in the form objects, you rarely need to parse it and can directly deal with the properties of the objects themselves. As long as the properties are named reasonably (and they usually are), you will be able to quickly get to the data you need.

Dealing with pipeline data

Since commands on the pipeline have access to object properties, several general-purpose cmdlets exist to perform common operations. Since these cmdlets can work with any kind of object, they use Object as the noun (you remember the Verb-Noun naming convention for cmdlets, right?).

To find the list of these cmdlets, we can use the Get-Command cmdlet:

Dealing with pipeline data

Tip

ft is an alias for the Format-Table cmdlet, which I'm using here to get the display to fit more nicely on the screen. It will be covered in depth in Chapter 5, Formatting Output.

The Sort-Object, Select-Object, and Where-Object cmdlets are some of the most used cmdlets in PowerShell.

The Sort-Object cmdlet

Sorting data can be interesting. Have you ever sorted a list of numbers only to find that 11 came between 1 and 2? That's because the sort that you used treated the numbers as text. Sorting dates with all the different culture-specific formatting can also be a challenge. Fortunately, PowerShell handles sorting details for you with the Sort-Object cmdlet.

Let's look at a few examples of the Sort-Object cmdlet before getting into the details. We'll start by sorting a directory listing by length:

The Sort-Object cmdlet

Sorting this in reverse isn't difficult either.

The Sort-Object cmdlet

Sorting by more than one property is a breeze as well. Here, I omitted the parameter name (-Property) to shorten the command-line a bit:

The Sort-Object cmdlet

Tip

You try it!

Use the Sort-object cmdlet in conjunction with dir (Get-ChildItem), Get-Service, or Get-Process. Try sorting by more than one property or in reverse. Note that the dates and numbers are sorted correctly, even though the text might not be alphabetically sorted.

Looking at the brief help for the Sort-Object cmdlet, we can see a few other parameters, such as:

  • -Unique (return distinct items found in the input)
  • -CaseSensitive (force a case-sensitive sort)
  • -Culture (specify what culture to use while sorting)

As it turns out, you will probably find few occasions to use these parameters and will be fine with the –Property and –Descending parameters.

The Where-Object cmdlet

Another cmdlet that is extremely useful is the Where-Object cmdlet. Where-Object is used to filter the pipeline data based on a condition that is tested for each item in the pipeline. Any object in the pipeline that causes the condition to evaluate to a true value is output from the Where-Object cmdlet. Objects that cause the condition to evaluate to a false value are not passed on as output.

For instance, we might want to find all the files that are below 100 bytes in size in the c:\temp directory. One way to do that is to use the simplified, or comparison syntax for Where-Object, which was introduced in PowerShell 3.0. In this syntax, the command would look like this:

Dir c:\temp | Where-Object Length –lt 100

In this syntax, we can compare a single property of each object with a constant value. The comparison operator here is –lt, which is how PowerShell expresses "less than".

Tip

All PowerShell comparison operators start with a dash. This can be confusing, but the < and > symbols have an entrenched meaning in shells, so they can't be used as operators. Common operators include -eq, -ne, -lt, -gt, -le, -ge, -not, and -like. For a full list of operators, try get-help about_operators.

If you need to use PowerShell 1.0 or 2.0, or need to specify a condition more complex than it is allowed in the simplified syntax, you can use the general or scriptblock syntax. Expressing the same condition using this form looks as follows:

Dir c:\temp | Where-Object {$_.Length –lt 100}

This looks a lot more complicated, but it's not so bad. The construction in curly braces is called a scriptblock, and is simply a block of the PowerShell code. In the scriptblock syntax, $_ stands for the current object in the pipeline and we're referencing the Length property of that object using dot-notation. The good thing about the general syntax of Where-Object is that we can do more inside the scriptblock than simply test one condition. For instance, we could check for files below 100 bytes or those that were created after 1/1/2015, as follows:

Dir c:\temp | Where-Object {$_.Length –lt 100 –or $_.CreationTime –gt '1/1/2015'}

Here's this command running on my laptop:

The Where-Object cmdlet

If you're using PowerShell 3.0 or above and need to use the scriptblock syntax, you can substitute $_ with $PSItem in the scriptblock. The meaning is the same and $PSItem is a bit more readable. It makes the line slightly longer, but it's a small sacrifice to make for readability's sake.

The examples that I've shown so far, have used simple comparisons with properties, but in the scriptblock syntax, any condition can be included. Also, note that any value other than a logical false value (expressed by $false in PowerShell), 0, or an empty string ('') is considered to be true ($true) in PowerShell. So, for example, we could filter objects using the Get-Member cmdlet to only show objects that have a particular property, as follows:

Dir | where-object {$_ | get-member Length}

This will return all objects in the current directory that have a Length property. Since files have lengths and directories don't, this is one way to get a list of files and omit the subdirectories.

Tip

You try it!

Use the Where-Object cmdlet to find all of the *.ps* files in $PSHOME that are larger than 1 kilobyte in size. Remember that you can express 1kilobyte using the KB unit suffix (1KB).

The Select-Object cmdlet

The Select-Object cmdlet is a versatile cmdlet that you will find yourself using often. There are three main ways that it is used:

  • Limiting the number of the objects returned
  • Limiting the properties of the objects returned
  • Retrieving the value of a single property of the objects in the pipeline

Limiting the number of objects returned

Sometimes, you just want to see a few of the objects that are in the pipeline. To accomplish this, you can use the -First, -Last, and -Skip parameters. The -First parameter indicates that you want to see a particular number of objects from the beginning of the list of objects in the pipeline. Similarly, the -Last parameter selects objects from the end of the list of objects in the pipeline.

For instance, getting the first two processes in the list from Get-Process is simple:

Limiting the number of objects returned

Since we didn't use Sort-Object to force the order of the objects in the pipeline, we don't know that these are the first alphabetically, but they were the first two that were output from Get-Process.

You can use –Skip to cause a certain number of objects to be bypassed before returning the objects. It can be used by itself to output the rest of the objects after the skipped ones, or in conjunction with –First or –Last to return all but the beginning or end of the list of objects. As an example, -Skip can be used to skip over header lines when reading a file using the Get-Content cmdlet.

Limiting the properties of the objects returned

Sometimes, the objects in the pipeline have more properties than you need. To select only certain properties from the list of objects in the pipeline, you can use the –Property parameter with a list of properties. For instance, to get only the Name, Extension, and Length from the directory listing, you could do something like this:

Limiting the properties of the objects returned

I used the –First parameter as well to save some space in the output, but the important thing is that we only got the three properties that we asked for.

Note that, here, the first two objects in the pipeline were directories, and directory objects don't have a length property. PowerShell provides an empty value of $null for missing properties like this. Also, note that these objects weren't formatted like a directory listing. We'll talk about formatting in detail in the next chapter, but for now, you should just know that these limited objects are not of the same type as the original objects, so the formatting system treated them differently.

Tip

You try it!

Use the Get-Member cmdlet to verify that the type of the objects change slightly when you use the –Property parameter of Select-Object.

Retrieving the values of a single property

Sometimes, you want to get the values of a single property of a set of objects. For instance, if you wanted to get the display names of all of the services installed on your computer, you might try to do something like this:

Retrieving the values of a single property

This is close to what you were looking for, but instead of getting a bunch of names (strings), you got a bunch of objects with the DisplayName properties. A hint that this is what happened is seen by the heading (and underline) of DisplayName. You can also verify this using the Get-Member cmdlet:

Retrieving the values of a single property

In order to just get the values and not objects, you need to use the –ExpandProperty parameter. Unlike the –Property parameter, you can only specify a single property with –ExpandProperty, and the output is a list of raw values. Notice that with –ExpandProperty, the column heading is gone:

Retrieving the values of a single property

We can also verify using Get-Member that we just got strings instead of objects with a DisplayName property:

Retrieving the values of a single property

There are a few other parameters for Select-Object, but they will be less commonly used than the ones listed here.

The Measure-Object cmdlet

The Measure-Object cmdlet has a simple function. It calculates statistics based on the objects in the pipeline. Its most basic form takes no parameters, and simply counts the objects that are in the pipeline.

To count the files in c:\temp and its subfolders, you could write:

Dir c:\temp –recurse –file | Measure-Object
The Measure-Object cmdlet

The output shows the count, and also some other properties that give a hint about the other uses of the cmdlet. To populate these other fields, you will need to provide the name of the property that is used to calculate them and also specify which field(s) you want to calculate. The calculations are specified using the –Sum, -Minimum, -Maximum, and –Average switches.

For instance, to add up (sum) the lengths of the files in the C:\Windows directory, you could issue this command:

Dir c:\Windows | Measure-Object –Property Length –Sum
The Measure-Object cmdlet

Tip

You try it!

Use the Measure-Object cmdlet to find the size of the largest file on your C:.

The Group-Object cmdlet

The Group-Object cmdlet divides the objects in the pipeline into distinct sets based on a property or a set of properties. For instance, we can categorize the files in a folder by their extensions using Group-Object like this:

The Group-Object cmdlet

You will notice in the output that PowerShell has provided the count of items in each set, the value of the property (Extension) that labels the set, and a property called Group, which contains all of the original objects that were on the pipeline that ended up in the set. If you have used the GROUP BY clause in SQL and are used to losing the original information when you group, you'll be pleased to know that PowerShell retains those objects in their original state in the Group property of the output.

Tip

You try it!

Can you think of a way to get the original objects out of the Group property? (Hint: one of the ways to use Select-Object might come in handy here.)

If you don't need the objects and are simply concerned with what the counts are, you can use the –NoElement switch, which causes the Group property to be omitted.

The Group-Object cmdlet

You're not limited to grouping by a single property either. If you want to see files grouped by mode (read-only, archive, etc.) and extension, you can simply list both properties.

The Group-Object cmdlet

Note that the Name property of each set is now a list of two values corresponding to the two properties defining the group.

The Group-Object cmdlet can be useful to summarize the objects, but you will probably not use it nearly as much as Sort-Object, Where-Object, and Select-Object.

The Sort-Object cmdlet

Sorting data can be interesting. Have you ever sorted a list of numbers only to find that 11 came between 1 and 2? That's because the sort that you used treated the numbers as text. Sorting dates with all the different culture-specific formatting can also be a challenge. Fortunately, PowerShell handles sorting details for you with the Sort-Object cmdlet.

Let's look at a few examples of the Sort-Object cmdlet before getting into the details. We'll start by sorting a directory listing by length:

The Sort-Object cmdlet

Sorting this in reverse isn't difficult either.

The Sort-Object cmdlet

Sorting by more than one property is a breeze as well. Here, I omitted the parameter name (-Property) to shorten the command-line a bit:

The Sort-Object cmdlet

Tip

You try it!

Use the Sort-object cmdlet in conjunction with dir (Get-ChildItem), Get-Service, or Get-Process. Try sorting by more than one property or in reverse. Note that the dates and numbers are sorted correctly, even though the text might not be alphabetically sorted.

Looking at the brief help for the Sort-Object cmdlet, we can see a few other parameters, such as:

  • -Unique (return distinct items found in the input)
  • -CaseSensitive (force a case-sensitive sort)
  • -Culture (specify what culture to use while sorting)

As it turns out, you will probably find few occasions to use these parameters and will be fine with the –Property and –Descending parameters.

The Where-Object cmdlet

Another cmdlet that is extremely useful is the Where-Object cmdlet. Where-Object is used to filter the pipeline data based on a condition that is tested for each item in the pipeline. Any object in the pipeline that causes the condition to evaluate to a true value is output from the Where-Object cmdlet. Objects that cause the condition to evaluate to a false value are not passed on as output.

For instance, we might want to find all the files that are below 100 bytes in size in the c:\temp directory. One way to do that is to use the simplified, or comparison syntax for Where-Object, which was introduced in PowerShell 3.0. In this syntax, the command would look like this:

Dir c:\temp | Where-Object Length –lt 100

In this syntax, we can compare a single property of each object with a constant value. The comparison operator here is –lt, which is how PowerShell expresses "less than".

Tip

All PowerShell comparison operators start with a dash. This can be confusing, but the < and > symbols have an entrenched meaning in shells, so they can't be used as operators. Common operators include -eq, -ne, -lt, -gt, -le, -ge, -not, and -like. For a full list of operators, try get-help about_operators.

If you need to use PowerShell 1.0 or 2.0, or need to specify a condition more complex than it is allowed in the simplified syntax, you can use the general or scriptblock syntax. Expressing the same condition using this form looks as follows:

Dir c:\temp | Where-Object {$_.Length –lt 100}

This looks a lot more complicated, but it's not so bad. The construction in curly braces is called a scriptblock, and is simply a block of the PowerShell code. In the scriptblock syntax, $_ stands for the current object in the pipeline and we're referencing the Length property of that object using dot-notation. The good thing about the general syntax of Where-Object is that we can do more inside the scriptblock than simply test one condition. For instance, we could check for files below 100 bytes or those that were created after 1/1/2015, as follows:

Dir c:\temp | Where-Object {$_.Length –lt 100 –or $_.CreationTime –gt '1/1/2015'}

Here's this command running on my laptop:

The Where-Object cmdlet

If you're using PowerShell 3.0 or above and need to use the scriptblock syntax, you can substitute $_ with $PSItem in the scriptblock. The meaning is the same and $PSItem is a bit more readable. It makes the line slightly longer, but it's a small sacrifice to make for readability's sake.

The examples that I've shown so far, have used simple comparisons with properties, but in the scriptblock syntax, any condition can be included. Also, note that any value other than a logical false value (expressed by $false in PowerShell), 0, or an empty string ('') is considered to be true ($true) in PowerShell. So, for example, we could filter objects using the Get-Member cmdlet to only show objects that have a particular property, as follows:

Dir | where-object {$_ | get-member Length}

This will return all objects in the current directory that have a Length property. Since files have lengths and directories don't, this is one way to get a list of files and omit the subdirectories.

Tip

You try it!

Use the Where-Object cmdlet to find all of the *.ps* files in $PSHOME that are larger than 1 kilobyte in size. Remember that you can express 1kilobyte using the KB unit suffix (1KB).

The Select-Object cmdlet

The Select-Object cmdlet is a versatile cmdlet that you will find yourself using often. There are three main ways that it is used:

  • Limiting the number of the objects returned
  • Limiting the properties of the objects returned
  • Retrieving the value of a single property of the objects in the pipeline

Limiting the number of objects returned

Sometimes, you just want to see a few of the objects that are in the pipeline. To accomplish this, you can use the -First, -Last, and -Skip parameters. The -First parameter indicates that you want to see a particular number of objects from the beginning of the list of objects in the pipeline. Similarly, the -Last parameter selects objects from the end of the list of objects in the pipeline.

For instance, getting the first two processes in the list from Get-Process is simple:

Limiting the number of objects returned

Since we didn't use Sort-Object to force the order of the objects in the pipeline, we don't know that these are the first alphabetically, but they were the first two that were output from Get-Process.

You can use –Skip to cause a certain number of objects to be bypassed before returning the objects. It can be used by itself to output the rest of the objects after the skipped ones, or in conjunction with –First or –Last to return all but the beginning or end of the list of objects. As an example, -Skip can be used to skip over header lines when reading a file using the Get-Content cmdlet.

Limiting the properties of the objects returned

Sometimes, the objects in the pipeline have more properties than you need. To select only certain properties from the list of objects in the pipeline, you can use the –Property parameter with a list of properties. For instance, to get only the Name, Extension, and Length from the directory listing, you could do something like this:

Limiting the properties of the objects returned

I used the –First parameter as well to save some space in the output, but the important thing is that we only got the three properties that we asked for.

Note that, here, the first two objects in the pipeline were directories, and directory objects don't have a length property. PowerShell provides an empty value of $null for missing properties like this. Also, note that these objects weren't formatted like a directory listing. We'll talk about formatting in detail in the next chapter, but for now, you should just know that these limited objects are not of the same type as the original objects, so the formatting system treated them differently.

Tip

You try it!

Use the Get-Member cmdlet to verify that the type of the objects change slightly when you use the –Property parameter of Select-Object.

Retrieving the values of a single property

Sometimes, you want to get the values of a single property of a set of objects. For instance, if you wanted to get the display names of all of the services installed on your computer, you might try to do something like this:

Retrieving the values of a single property

This is close to what you were looking for, but instead of getting a bunch of names (strings), you got a bunch of objects with the DisplayName properties. A hint that this is what happened is seen by the heading (and underline) of DisplayName. You can also verify this using the Get-Member cmdlet:

Retrieving the values of a single property

In order to just get the values and not objects, you need to use the –ExpandProperty parameter. Unlike the –Property parameter, you can only specify a single property with –ExpandProperty, and the output is a list of raw values. Notice that with –ExpandProperty, the column heading is gone:

Retrieving the values of a single property

We can also verify using Get-Member that we just got strings instead of objects with a DisplayName property:

Retrieving the values of a single property

There are a few other parameters for Select-Object, but they will be less commonly used than the ones listed here.

The Measure-Object cmdlet

The Measure-Object cmdlet has a simple function. It calculates statistics based on the objects in the pipeline. Its most basic form takes no parameters, and simply counts the objects that are in the pipeline.

To count the files in c:\temp and its subfolders, you could write:

Dir c:\temp –recurse –file | Measure-Object
The Measure-Object cmdlet

The output shows the count, and also some other properties that give a hint about the other uses of the cmdlet. To populate these other fields, you will need to provide the name of the property that is used to calculate them and also specify which field(s) you want to calculate. The calculations are specified using the –Sum, -Minimum, -Maximum, and –Average switches.

For instance, to add up (sum) the lengths of the files in the C:\Windows directory, you could issue this command:

Dir c:\Windows | Measure-Object –Property Length –Sum
The Measure-Object cmdlet

Tip

You try it!

Use the Measure-Object cmdlet to find the size of the largest file on your C:.

The Group-Object cmdlet

The Group-Object cmdlet divides the objects in the pipeline into distinct sets based on a property or a set of properties. For instance, we can categorize the files in a folder by their extensions using Group-Object like this:

The Group-Object cmdlet

You will notice in the output that PowerShell has provided the count of items in each set, the value of the property (Extension) that labels the set, and a property called Group, which contains all of the original objects that were on the pipeline that ended up in the set. If you have used the GROUP BY clause in SQL and are used to losing the original information when you group, you'll be pleased to know that PowerShell retains those objects in their original state in the Group property of the output.

Tip

You try it!

Can you think of a way to get the original objects out of the Group property? (Hint: one of the ways to use Select-Object might come in handy here.)

If you don't need the objects and are simply concerned with what the counts are, you can use the –NoElement switch, which causes the Group property to be omitted.

The Group-Object cmdlet

You're not limited to grouping by a single property either. If you want to see files grouped by mode (read-only, archive, etc.) and extension, you can simply list both properties.

The Group-Object cmdlet

Note that the Name property of each set is now a list of two values corresponding to the two properties defining the group.

The Group-Object cmdlet can be useful to summarize the objects, but you will probably not use it nearly as much as Sort-Object, Where-Object, and Select-Object.

The Where-Object cmdlet

Another cmdlet that is extremely useful is the Where-Object cmdlet. Where-Object is used to filter the pipeline data based on a condition that is tested for each item in the pipeline. Any object in the pipeline that causes the condition to evaluate to a true value is output from the Where-Object cmdlet. Objects that cause the condition to evaluate to a false value are not passed on as output.

For instance, we might want to find all the files that are below 100 bytes in size in the c:\temp directory. One way to do that is to use the simplified, or comparison syntax for Where-Object, which was introduced in PowerShell 3.0. In this syntax, the command would look like this:

Dir c:\temp | Where-Object Length –lt 100

In this syntax, we can compare a single property of each object with a constant value. The comparison operator here is –lt, which is how PowerShell expresses "less than".

Tip

All PowerShell comparison operators start with a dash. This can be confusing, but the < and > symbols have an entrenched meaning in shells, so they can't be used as operators. Common operators include -eq, -ne, -lt, -gt, -le, -ge, -not, and -like. For a full list of operators, try get-help about_operators.

If you need to use PowerShell 1.0 or 2.0, or need to specify a condition more complex than it is allowed in the simplified syntax, you can use the general or scriptblock syntax. Expressing the same condition using this form looks as follows:

Dir c:\temp | Where-Object {$_.Length –lt 100}

This looks a lot more complicated, but it's not so bad. The construction in curly braces is called a scriptblock, and is simply a block of the PowerShell code. In the scriptblock syntax, $_ stands for the current object in the pipeline and we're referencing the Length property of that object using dot-notation. The good thing about the general syntax of Where-Object is that we can do more inside the scriptblock than simply test one condition. For instance, we could check for files below 100 bytes or those that were created after 1/1/2015, as follows:

Dir c:\temp | Where-Object {$_.Length –lt 100 –or $_.CreationTime –gt '1/1/2015'}

Here's this command running on my laptop:

The Where-Object cmdlet

If you're using PowerShell 3.0 or above and need to use the scriptblock syntax, you can substitute $_ with $PSItem in the scriptblock. The meaning is the same and $PSItem is a bit more readable. It makes the line slightly longer, but it's a small sacrifice to make for readability's sake.

The examples that I've shown so far, have used simple comparisons with properties, but in the scriptblock syntax, any condition can be included. Also, note that any value other than a logical false value (expressed by $false in PowerShell), 0, or an empty string ('') is considered to be true ($true) in PowerShell. So, for example, we could filter objects using the Get-Member cmdlet to only show objects that have a particular property, as follows:

Dir | where-object {$_ | get-member Length}

This will return all objects in the current directory that have a Length property. Since files have lengths and directories don't, this is one way to get a list of files and omit the subdirectories.

Tip

You try it!

Use the Where-Object cmdlet to find all of the *.ps* files in $PSHOME that are larger than 1 kilobyte in size. Remember that you can express 1kilobyte using the KB unit suffix (1KB).

The Select-Object cmdlet

The Select-Object cmdlet is a versatile cmdlet that you will find yourself using often. There are three main ways that it is used:

  • Limiting the number of the objects returned
  • Limiting the properties of the objects returned
  • Retrieving the value of a single property of the objects in the pipeline

Limiting the number of objects returned

Sometimes, you just want to see a few of the objects that are in the pipeline. To accomplish this, you can use the -First, -Last, and -Skip parameters. The -First parameter indicates that you want to see a particular number of objects from the beginning of the list of objects in the pipeline. Similarly, the -Last parameter selects objects from the end of the list of objects in the pipeline.

For instance, getting the first two processes in the list from Get-Process is simple:

Limiting the number of objects returned

Since we didn't use Sort-Object to force the order of the objects in the pipeline, we don't know that these are the first alphabetically, but they were the first two that were output from Get-Process.

You can use –Skip to cause a certain number of objects to be bypassed before returning the objects. It can be used by itself to output the rest of the objects after the skipped ones, or in conjunction with –First or –Last to return all but the beginning or end of the list of objects. As an example, -Skip can be used to skip over header lines when reading a file using the Get-Content cmdlet.

Limiting the properties of the objects returned

Sometimes, the objects in the pipeline have more properties than you need. To select only certain properties from the list of objects in the pipeline, you can use the –Property parameter with a list of properties. For instance, to get only the Name, Extension, and Length from the directory listing, you could do something like this:

Limiting the properties of the objects returned

I used the –First parameter as well to save some space in the output, but the important thing is that we only got the three properties that we asked for.

Note that, here, the first two objects in the pipeline were directories, and directory objects don't have a length property. PowerShell provides an empty value of $null for missing properties like this. Also, note that these objects weren't formatted like a directory listing. We'll talk about formatting in detail in the next chapter, but for now, you should just know that these limited objects are not of the same type as the original objects, so the formatting system treated them differently.

Tip

You try it!

Use the Get-Member cmdlet to verify that the type of the objects change slightly when you use the –Property parameter of Select-Object.

Retrieving the values of a single property

Sometimes, you want to get the values of a single property of a set of objects. For instance, if you wanted to get the display names of all of the services installed on your computer, you might try to do something like this:

Retrieving the values of a single property

This is close to what you were looking for, but instead of getting a bunch of names (strings), you got a bunch of objects with the DisplayName properties. A hint that this is what happened is seen by the heading (and underline) of DisplayName. You can also verify this using the Get-Member cmdlet:

Retrieving the values of a single property

In order to just get the values and not objects, you need to use the –ExpandProperty parameter. Unlike the –Property parameter, you can only specify a single property with –ExpandProperty, and the output is a list of raw values. Notice that with –ExpandProperty, the column heading is gone:

Retrieving the values of a single property

We can also verify using Get-Member that we just got strings instead of objects with a DisplayName property:

Retrieving the values of a single property

There are a few other parameters for Select-Object, but they will be less commonly used than the ones listed here.

The Measure-Object cmdlet

The Measure-Object cmdlet has a simple function. It calculates statistics based on the objects in the pipeline. Its most basic form takes no parameters, and simply counts the objects that are in the pipeline.

To count the files in c:\temp and its subfolders, you could write:

Dir c:\temp –recurse –file | Measure-Object
The Measure-Object cmdlet

The output shows the count, and also some other properties that give a hint about the other uses of the cmdlet. To populate these other fields, you will need to provide the name of the property that is used to calculate them and also specify which field(s) you want to calculate. The calculations are specified using the –Sum, -Minimum, -Maximum, and –Average switches.

For instance, to add up (sum) the lengths of the files in the C:\Windows directory, you could issue this command:

Dir c:\Windows | Measure-Object –Property Length –Sum
The Measure-Object cmdlet

Tip

You try it!

Use the Measure-Object cmdlet to find the size of the largest file on your C:.

The Group-Object cmdlet

The Group-Object cmdlet divides the objects in the pipeline into distinct sets based on a property or a set of properties. For instance, we can categorize the files in a folder by their extensions using Group-Object like this:

The Group-Object cmdlet

You will notice in the output that PowerShell has provided the count of items in each set, the value of the property (Extension) that labels the set, and a property called Group, which contains all of the original objects that were on the pipeline that ended up in the set. If you have used the GROUP BY clause in SQL and are used to losing the original information when you group, you'll be pleased to know that PowerShell retains those objects in their original state in the Group property of the output.

Tip

You try it!

Can you think of a way to get the original objects out of the Group property? (Hint: one of the ways to use Select-Object might come in handy here.)

If you don't need the objects and are simply concerned with what the counts are, you can use the –NoElement switch, which causes the Group property to be omitted.

The Group-Object cmdlet

You're not limited to grouping by a single property either. If you want to see files grouped by mode (read-only, archive, etc.) and extension, you can simply list both properties.

The Group-Object cmdlet

Note that the Name property of each set is now a list of two values corresponding to the two properties defining the group.

The Group-Object cmdlet can be useful to summarize the objects, but you will probably not use it nearly as much as Sort-Object, Where-Object, and Select-Object.

The Select-Object cmdlet

The Select-Object cmdlet is a versatile cmdlet that you will find yourself using often. There are three main ways that it is used:

  • Limiting the number of the objects returned
  • Limiting the properties of the objects returned
  • Retrieving the value of a single property of the objects in the pipeline

Limiting the number of objects returned

Sometimes, you just want to see a few of the objects that are in the pipeline. To accomplish this, you can use the -First, -Last, and -Skip parameters. The -First parameter indicates that you want to see a particular number of objects from the beginning of the list of objects in the pipeline. Similarly, the -Last parameter selects objects from the end of the list of objects in the pipeline.

For instance, getting the first two processes in the list from Get-Process is simple:

Limiting the number of objects returned

Since we didn't use Sort-Object to force the order of the objects in the pipeline, we don't know that these are the first alphabetically, but they were the first two that were output from Get-Process.

You can use –Skip to cause a certain number of objects to be bypassed before returning the objects. It can be used by itself to output the rest of the objects after the skipped ones, or in conjunction with –First or –Last to return all but the beginning or end of the list of objects. As an example, -Skip can be used to skip over header lines when reading a file using the Get-Content cmdlet.

Limiting the properties of the objects returned

Sometimes, the objects in the pipeline have more properties than you need. To select only certain properties from the list of objects in the pipeline, you can use the –Property parameter with a list of properties. For instance, to get only the Name, Extension, and Length from the directory listing, you could do something like this:

Limiting the properties of the objects returned

I used the –First parameter as well to save some space in the output, but the important thing is that we only got the three properties that we asked for.

Note that, here, the first two objects in the pipeline were directories, and directory objects don't have a length property. PowerShell provides an empty value of $null for missing properties like this. Also, note that these objects weren't formatted like a directory listing. We'll talk about formatting in detail in the next chapter, but for now, you should just know that these limited objects are not of the same type as the original objects, so the formatting system treated them differently.

Tip

You try it!

Use the Get-Member cmdlet to verify that the type of the objects change slightly when you use the –Property parameter of Select-Object.

Retrieving the values of a single property

Sometimes, you want to get the values of a single property of a set of objects. For instance, if you wanted to get the display names of all of the services installed on your computer, you might try to do something like this:

Retrieving the values of a single property

This is close to what you were looking for, but instead of getting a bunch of names (strings), you got a bunch of objects with the DisplayName properties. A hint that this is what happened is seen by the heading (and underline) of DisplayName. You can also verify this using the Get-Member cmdlet:

Retrieving the values of a single property

In order to just get the values and not objects, you need to use the –ExpandProperty parameter. Unlike the –Property parameter, you can only specify a single property with –ExpandProperty, and the output is a list of raw values. Notice that with –ExpandProperty, the column heading is gone:

Retrieving the values of a single property

We can also verify using Get-Member that we just got strings instead of objects with a DisplayName property:

Retrieving the values of a single property

There are a few other parameters for Select-Object, but they will be less commonly used than the ones listed here.

The Measure-Object cmdlet

The Measure-Object cmdlet has a simple function. It calculates statistics based on the objects in the pipeline. Its most basic form takes no parameters, and simply counts the objects that are in the pipeline.

To count the files in c:\temp and its subfolders, you could write:

Dir c:\temp –recurse –file | Measure-Object
The Measure-Object cmdlet

The output shows the count, and also some other properties that give a hint about the other uses of the cmdlet. To populate these other fields, you will need to provide the name of the property that is used to calculate them and also specify which field(s) you want to calculate. The calculations are specified using the –Sum, -Minimum, -Maximum, and –Average switches.

For instance, to add up (sum) the lengths of the files in the C:\Windows directory, you could issue this command:

Dir c:\Windows | Measure-Object –Property Length –Sum
The Measure-Object cmdlet

Tip

You try it!

Use the Measure-Object cmdlet to find the size of the largest file on your C:.

The Group-Object cmdlet

The Group-Object cmdlet divides the objects in the pipeline into distinct sets based on a property or a set of properties. For instance, we can categorize the files in a folder by their extensions using Group-Object like this:

The Group-Object cmdlet

You will notice in the output that PowerShell has provided the count of items in each set, the value of the property (Extension) that labels the set, and a property called Group, which contains all of the original objects that were on the pipeline that ended up in the set. If you have used the GROUP BY clause in SQL and are used to losing the original information when you group, you'll be pleased to know that PowerShell retains those objects in their original state in the Group property of the output.

Tip

You try it!

Can you think of a way to get the original objects out of the Group property? (Hint: one of the ways to use Select-Object might come in handy here.)

If you don't need the objects and are simply concerned with what the counts are, you can use the –NoElement switch, which causes the Group property to be omitted.

The Group-Object cmdlet

You're not limited to grouping by a single property either. If you want to see files grouped by mode (read-only, archive, etc.) and extension, you can simply list both properties.

The Group-Object cmdlet

Note that the Name property of each set is now a list of two values corresponding to the two properties defining the group.

The Group-Object cmdlet can be useful to summarize the objects, but you will probably not use it nearly as much as Sort-Object, Where-Object, and Select-Object.

Limiting the number of objects returned

Sometimes, you just want to see a few of the objects that are in the pipeline. To accomplish this, you can use the -First, -Last, and -Skip parameters. The -First parameter indicates that you want to see a particular number of objects from the beginning of the list of objects in the pipeline. Similarly, the -Last parameter selects objects from the end of the list of objects in the pipeline.

For instance, getting the first two processes in the list from Get-Process is simple:

Limiting the number of objects returned

Since we didn't use Sort-Object to force the order of the objects in the pipeline, we don't know that these are the first alphabetically, but they were the first two that were output from Get-Process.

You can use –Skip to cause a certain number of objects to be bypassed before returning the objects. It can be used by itself to output the rest of the objects after the skipped ones, or in conjunction with –First or –Last to return all but the beginning or end of the list of objects. As an example, -Skip can be used to skip over header lines when reading a file using the Get-Content cmdlet.

Limiting the properties of the objects returned

Sometimes, the objects in the pipeline have more properties than you need. To select only certain properties from the list of objects in the pipeline, you can use the –Property parameter with a list of properties. For instance, to get only the Name, Extension, and Length from the directory listing, you could do something like this:

Limiting the properties of the objects returned

I used the –First parameter as well to save some space in the output, but the important thing is that we only got the three properties that we asked for.

Note that, here, the first two objects in the pipeline were directories, and directory objects don't have a length property. PowerShell provides an empty value of $null for missing properties like this. Also, note that these objects weren't formatted like a directory listing. We'll talk about formatting in detail in the next chapter, but for now, you should just know that these limited objects are not of the same type as the original objects, so the formatting system treated them differently.

Tip

You try it!

Use the Get-Member cmdlet to verify that the type of the objects change slightly when you use the –Property parameter of Select-Object.

Retrieving the values of a single property

Sometimes, you want to get the values of a single property of a set of objects. For instance, if you wanted to get the display names of all of the services installed on your computer, you might try to do something like this:

Retrieving the values of a single property

This is close to what you were looking for, but instead of getting a bunch of names (strings), you got a bunch of objects with the DisplayName properties. A hint that this is what happened is seen by the heading (and underline) of DisplayName. You can also verify this using the Get-Member cmdlet:

Retrieving the values of a single property

In order to just get the values and not objects, you need to use the –ExpandProperty parameter. Unlike the –Property parameter, you can only specify a single property with –ExpandProperty, and the output is a list of raw values. Notice that with –ExpandProperty, the column heading is gone:

Retrieving the values of a single property

We can also verify using Get-Member that we just got strings instead of objects with a DisplayName property:

Retrieving the values of a single property

There are a few other parameters for Select-Object, but they will be less commonly used than the ones listed here.

The Measure-Object cmdlet

The Measure-Object cmdlet has a simple function. It calculates statistics based on the objects in the pipeline. Its most basic form takes no parameters, and simply counts the objects that are in the pipeline.

To count the files in c:\temp and its subfolders, you could write:

Dir c:\temp –recurse –file | Measure-Object
The Measure-Object cmdlet

The output shows the count, and also some other properties that give a hint about the other uses of the cmdlet. To populate these other fields, you will need to provide the name of the property that is used to calculate them and also specify which field(s) you want to calculate. The calculations are specified using the –Sum, -Minimum, -Maximum, and –Average switches.

For instance, to add up (sum) the lengths of the files in the C:\Windows directory, you could issue this command:

Dir c:\Windows | Measure-Object –Property Length –Sum
The Measure-Object cmdlet

Tip

You try it!

Use the Measure-Object cmdlet to find the size of the largest file on your C:.

The Group-Object cmdlet

The Group-Object cmdlet divides the objects in the pipeline into distinct sets based on a property or a set of properties. For instance, we can categorize the files in a folder by their extensions using Group-Object like this:

The Group-Object cmdlet

You will notice in the output that PowerShell has provided the count of items in each set, the value of the property (Extension) that labels the set, and a property called Group, which contains all of the original objects that were on the pipeline that ended up in the set. If you have used the GROUP BY clause in SQL and are used to losing the original information when you group, you'll be pleased to know that PowerShell retains those objects in their original state in the Group property of the output.

Tip

You try it!

Can you think of a way to get the original objects out of the Group property? (Hint: one of the ways to use Select-Object might come in handy here.)

If you don't need the objects and are simply concerned with what the counts are, you can use the –NoElement switch, which causes the Group property to be omitted.

The Group-Object cmdlet

You're not limited to grouping by a single property either. If you want to see files grouped by mode (read-only, archive, etc.) and extension, you can simply list both properties.

The Group-Object cmdlet

Note that the Name property of each set is now a list of two values corresponding to the two properties defining the group.

The Group-Object cmdlet can be useful to summarize the objects, but you will probably not use it nearly as much as Sort-Object, Where-Object, and Select-Object.

Limiting the properties of the objects returned

Sometimes, the objects in the pipeline have more properties than you need. To select only certain properties from the list of objects in the pipeline, you can use the –Property parameter with a list of properties. For instance, to get only the Name, Extension, and Length from the directory listing, you could do something like this:

Limiting the properties of the objects returned

I used the –First parameter as well to save some space in the output, but the important thing is that we only got the three properties that we asked for.

Note that, here, the first two objects in the pipeline were directories, and directory objects don't have a length property. PowerShell provides an empty value of $null for missing properties like this. Also, note that these objects weren't formatted like a directory listing. We'll talk about formatting in detail in the next chapter, but for now, you should just know that these limited objects are not of the same type as the original objects, so the formatting system treated them differently.

Tip

You try it!

Use the Get-Member cmdlet to verify that the type of the objects change slightly when you use the –Property parameter of Select-Object.

Retrieving the values of a single property

Sometimes, you want to get the values of a single property of a set of objects. For instance, if you wanted to get the display names of all of the services installed on your computer, you might try to do something like this:

Retrieving the values of a single property

This is close to what you were looking for, but instead of getting a bunch of names (strings), you got a bunch of objects with the DisplayName properties. A hint that this is what happened is seen by the heading (and underline) of DisplayName. You can also verify this using the Get-Member cmdlet:

Retrieving the values of a single property

In order to just get the values and not objects, you need to use the –ExpandProperty parameter. Unlike the –Property parameter, you can only specify a single property with –ExpandProperty, and the output is a list of raw values. Notice that with –ExpandProperty, the column heading is gone:

Retrieving the values of a single property

We can also verify using Get-Member that we just got strings instead of objects with a DisplayName property:

Retrieving the values of a single property

There are a few other parameters for Select-Object, but they will be less commonly used than the ones listed here.

The Measure-Object cmdlet

The Measure-Object cmdlet has a simple function. It calculates statistics based on the objects in the pipeline. Its most basic form takes no parameters, and simply counts the objects that are in the pipeline.

To count the files in c:\temp and its subfolders, you could write:

Dir c:\temp –recurse –file | Measure-Object
The Measure-Object cmdlet

The output shows the count, and also some other properties that give a hint about the other uses of the cmdlet. To populate these other fields, you will need to provide the name of the property that is used to calculate them and also specify which field(s) you want to calculate. The calculations are specified using the –Sum, -Minimum, -Maximum, and –Average switches.

For instance, to add up (sum) the lengths of the files in the C:\Windows directory, you could issue this command:

Dir c:\Windows | Measure-Object –Property Length –Sum
The Measure-Object cmdlet

Tip

You try it!

Use the Measure-Object cmdlet to find the size of the largest file on your C:.

The Group-Object cmdlet

The Group-Object cmdlet divides the objects in the pipeline into distinct sets based on a property or a set of properties. For instance, we can categorize the files in a folder by their extensions using Group-Object like this:

The Group-Object cmdlet

You will notice in the output that PowerShell has provided the count of items in each set, the value of the property (Extension) that labels the set, and a property called Group, which contains all of the original objects that were on the pipeline that ended up in the set. If you have used the GROUP BY clause in SQL and are used to losing the original information when you group, you'll be pleased to know that PowerShell retains those objects in their original state in the Group property of the output.

Tip

You try it!

Can you think of a way to get the original objects out of the Group property? (Hint: one of the ways to use Select-Object might come in handy here.)

If you don't need the objects and are simply concerned with what the counts are, you can use the –NoElement switch, which causes the Group property to be omitted.

The Group-Object cmdlet

You're not limited to grouping by a single property either. If you want to see files grouped by mode (read-only, archive, etc.) and extension, you can simply list both properties.

The Group-Object cmdlet

Note that the Name property of each set is now a list of two values corresponding to the two properties defining the group.

The Group-Object cmdlet can be useful to summarize the objects, but you will probably not use it nearly as much as Sort-Object, Where-Object, and Select-Object.

Retrieving the values of a single property

Sometimes, you want to get the values of a single property of a set of objects. For instance, if you wanted to get the display names of all of the services installed on your computer, you might try to do something like this:

Retrieving the values of a single property

This is close to what you were looking for, but instead of getting a bunch of names (strings), you got a bunch of objects with the DisplayName properties. A hint that this is what happened is seen by the heading (and underline) of DisplayName. You can also verify this using the Get-Member cmdlet:

Retrieving the values of a single property

In order to just get the values and not objects, you need to use the –ExpandProperty parameter. Unlike the –Property parameter, you can only specify a single property with –ExpandProperty, and the output is a list of raw values. Notice that with –ExpandProperty, the column heading is gone:

Retrieving the values of a single property

We can also verify using Get-Member that we just got strings instead of objects with a DisplayName property:

Retrieving the values of a single property

There are a few other parameters for Select-Object, but they will be less commonly used than the ones listed here.

The Measure-Object cmdlet

The Measure-Object cmdlet has a simple function. It calculates statistics based on the objects in the pipeline. Its most basic form takes no parameters, and simply counts the objects that are in the pipeline.

To count the files in c:\temp and its subfolders, you could write:

Dir c:\temp –recurse –file | Measure-Object
The Measure-Object cmdlet

The output shows the count, and also some other properties that give a hint about the other uses of the cmdlet. To populate these other fields, you will need to provide the name of the property that is used to calculate them and also specify which field(s) you want to calculate. The calculations are specified using the –Sum, -Minimum, -Maximum, and –Average switches.

For instance, to add up (sum) the lengths of the files in the C:\Windows directory, you could issue this command:

Dir c:\Windows | Measure-Object –Property Length –Sum
The Measure-Object cmdlet

Tip

You try it!

Use the Measure-Object cmdlet to find the size of the largest file on your C:.

The Group-Object cmdlet

The Group-Object cmdlet divides the objects in the pipeline into distinct sets based on a property or a set of properties. For instance, we can categorize the files in a folder by their extensions using Group-Object like this:

The Group-Object cmdlet

You will notice in the output that PowerShell has provided the count of items in each set, the value of the property (Extension) that labels the set, and a property called Group, which contains all of the original objects that were on the pipeline that ended up in the set. If you have used the GROUP BY clause in SQL and are used to losing the original information when you group, you'll be pleased to know that PowerShell retains those objects in their original state in the Group property of the output.

Tip

You try it!

Can you think of a way to get the original objects out of the Group property? (Hint: one of the ways to use Select-Object might come in handy here.)

If you don't need the objects and are simply concerned with what the counts are, you can use the –NoElement switch, which causes the Group property to be omitted.

The Group-Object cmdlet

You're not limited to grouping by a single property either. If you want to see files grouped by mode (read-only, archive, etc.) and extension, you can simply list both properties.

The Group-Object cmdlet

Note that the Name property of each set is now a list of two values corresponding to the two properties defining the group.

The Group-Object cmdlet can be useful to summarize the objects, but you will probably not use it nearly as much as Sort-Object, Where-Object, and Select-Object.

The Measure-Object cmdlet

The Measure-Object cmdlet has a simple function. It calculates statistics based on the objects in the pipeline. Its most basic form takes no parameters, and simply counts the objects that are in the pipeline.

To count the files in c:\temp and its subfolders, you could write:

Dir c:\temp –recurse –file | Measure-Object
The Measure-Object cmdlet

The output shows the count, and also some other properties that give a hint about the other uses of the cmdlet. To populate these other fields, you will need to provide the name of the property that is used to calculate them and also specify which field(s) you want to calculate. The calculations are specified using the –Sum, -Minimum, -Maximum, and –Average switches.

For instance, to add up (sum) the lengths of the files in the C:\Windows directory, you could issue this command:

Dir c:\Windows | Measure-Object –Property Length –Sum
The Measure-Object cmdlet

Tip

You try it!

Use the Measure-Object cmdlet to find the size of the largest file on your C:.

The Group-Object cmdlet

The Group-Object cmdlet divides the objects in the pipeline into distinct sets based on a property or a set of properties. For instance, we can categorize the files in a folder by their extensions using Group-Object like this:

The Group-Object cmdlet

You will notice in the output that PowerShell has provided the count of items in each set, the value of the property (Extension) that labels the set, and a property called Group, which contains all of the original objects that were on the pipeline that ended up in the set. If you have used the GROUP BY clause in SQL and are used to losing the original information when you group, you'll be pleased to know that PowerShell retains those objects in their original state in the Group property of the output.

Tip

You try it!

Can you think of a way to get the original objects out of the Group property? (Hint: one of the ways to use Select-Object might come in handy here.)

If you don't need the objects and are simply concerned with what the counts are, you can use the –NoElement switch, which causes the Group property to be omitted.

The Group-Object cmdlet

You're not limited to grouping by a single property either. If you want to see files grouped by mode (read-only, archive, etc.) and extension, you can simply list both properties.

The Group-Object cmdlet

Note that the Name property of each set is now a list of two values corresponding to the two properties defining the group.

The Group-Object cmdlet can be useful to summarize the objects, but you will probably not use it nearly as much as Sort-Object, Where-Object, and Select-Object.

The Group-Object cmdlet

The Group-Object cmdlet divides the objects in the pipeline into distinct sets based on a property or a set of properties. For instance, we can categorize the files in a folder by their extensions using Group-Object like this:

The Group-Object cmdlet

You will notice in the output that PowerShell has provided the count of items in each set, the value of the property (Extension) that labels the set, and a property called Group, which contains all of the original objects that were on the pipeline that ended up in the set. If you have used the GROUP BY clause in SQL and are used to losing the original information when you group, you'll be pleased to know that PowerShell retains those objects in their original state in the Group property of the output.

Tip

You try it!

Can you think of a way to get the original objects out of the Group property? (Hint: one of the ways to use Select-Object might come in handy here.)

If you don't need the objects and are simply concerned with what the counts are, you can use the –NoElement switch, which causes the Group property to be omitted.

The Group-Object cmdlet

You're not limited to grouping by a single property either. If you want to see files grouped by mode (read-only, archive, etc.) and extension, you can simply list both properties.

The Group-Object cmdlet

Note that the Name property of each set is now a list of two values corresponding to the two properties defining the group.

The Group-Object cmdlet can be useful to summarize the objects, but you will probably not use it nearly as much as Sort-Object, Where-Object, and Select-Object.

Putting them together

The several *-Object cmdlets that we've discussed in this chapter will be the foundation to your experience with PowerShell. Although, we only used them with Dir, Get-Service, and Get-Process, this is only because I can be sure that you can use these cmdlets on any system. The way that you use the *-Object cmdlets is the same whether you're dealing with files and folders, virtual machines, or mailboxes in Exchange. Since PowerShell gives you objects in all of these situations, these cmdlets will enable you to manipulate them using the same techniques.

Here are a couple of concrete examples of how the methods of using these cmdlets are portable between the types of objects. First, to get the largest five files in the c:\Windows folder, you would do this:

Dir c:\Windows | Sort-Object –Property Length –Descending | Select-Object –First 5

Similarly, getting the five processes that are using the most file handles would look like this:

Get-Process | Sort-Object –Property Handles –Descending | Select-Object –First 5

Can you see that the methodology to solve these two problems is exactly the same? Can you think of other problems that you might solve using a similar approach?

Tip

You Try it!

Use the cmdlets in this chapter to find the five newest files on your C: drive (use the LastWriteTime property to determine the age).

Summary

In this chapter, we looked at how to use the pipeline in PowerShell and several of the cmdlets that deal with objects in general. Once you learn to use these cmdlets efficiently, you will be able to solve all kinds of interesting problems in many areas.

In the next chapter, we will investigate PowerShell's versatile formatting system and learn how to format output in different ways.

For further reading

  • Get-Help about_pipelines
  • Get-Help Sort-Object
  • Get-Help Where-Object
  • Get-Help Select-Object
  • Get-Help Group-Object
  • Get-Help about_comparison_operators
  • Get-Help about_scriptblocks